Compare commits

..

No commits in common. "127596687b0f5a29be65adfe80c40059edc4cc50" and "abd3317a10535203adab0bda236c4ace66435b63" have entirely different histories.

24 changed files with 73 additions and 156 deletions

View file

@ -35,6 +35,7 @@ regex = "1.6.0"
fancy-regex = "0.11.0"
thiserror = "1.0.36"
url = "2.2.2"
log = "0.4.17"
reqwest = { version = "0.11.11", default-features = false, features = [
"json",
"gzip",
@ -59,10 +60,11 @@ ress = "0.11.4"
phf = "0.11.1"
base64 = "0.21.0"
urlencoding = "2.1.2"
quick-xml = { version = "0.30.0", features = ["serialize"], optional = true }
tracing = { version = "0.1.37", features = ["log"] }
quick-xml = { version = "0.29.0", features = ["serialize"], optional = true }
[dev-dependencies]
env_logger = "0.10.0"
test-log = "0.2.11"
rstest = "0.18.1"
tokio-test = "0.4.2"
insta = { version = "1.17.1", features = ["ron", "redactions"] }

View file

@ -47,7 +47,7 @@ indicatif = "0.17.0"
futures = "0.3.21"
anyhow = "1.0"
clap = { version = "4.0.29", features = ["derive"] }
tracing-subscriber = "0.3.17"
env_logger = "0.10.0"
serde = "1.0"
serde_json = "1.0.82"
serde_yaml = "0.9.19"

View file

@ -390,8 +390,7 @@ async fn download_videos(
#[tokio::main]
async fn main() {
// env_logger::builder().format_timestamp_micros().init();
tracing_subscriber::fmt::init();
env_logger::builder().format_timestamp_micros().init();
let cli = Cli::parse();

View file

@ -20,7 +20,7 @@ use std::{
path::{Path, PathBuf},
};
use tracing::error;
use log::error;
pub(crate) const DEFAULT_CACHE_FILE: &str = "rustypipe_cache.json";

View file

@ -1,5 +1,3 @@
use std::fmt::Debug;
use serde::Serialize;
use url::Url;
@ -80,8 +78,7 @@ impl RustyPipeQuery {
}
/// Get the videos from a YouTube channel
#[tracing::instrument(skip(self))]
pub async fn channel_videos<S: AsRef<str> + Debug>(
pub async fn channel_videos<S: AsRef<str>>(
&self,
channel_id: S,
) -> Result<Channel<Paginator<VideoItem>>, Error> {
@ -92,8 +89,7 @@ impl RustyPipeQuery {
/// Get a ordered list of videos from a YouTube channel
///
/// This function does not return channel metadata.
#[tracing::instrument(skip(self))]
pub async fn channel_videos_order<S: AsRef<str> + Debug>(
pub async fn channel_videos_order<S: AsRef<str>>(
&self,
channel_id: S,
order: ChannelOrder,
@ -103,8 +99,7 @@ impl RustyPipeQuery {
}
/// Get the videos of the given tab (Shorts, Livestreams) from a YouTube channel
#[tracing::instrument(skip(self))]
pub async fn channel_videos_tab<S: AsRef<str> + Debug>(
pub async fn channel_videos_tab<S: AsRef<str>>(
&self,
channel_id: S,
tab: ChannelVideoTab,
@ -116,8 +111,7 @@ impl RustyPipeQuery {
/// Get a ordered list of videos from the given tab (Shorts, Livestreams) of a YouTube channel
///
/// This function does not return channel metadata.
#[tracing::instrument(skip(self))]
pub async fn channel_videos_tab_order<S: AsRef<str> + Debug>(
pub async fn channel_videos_tab_order<S: AsRef<str>>(
&self,
channel_id: S,
tab: ChannelVideoTab,
@ -134,8 +128,7 @@ impl RustyPipeQuery {
}
/// Search the videos of a channel
#[tracing::instrument(skip(self))]
pub async fn channel_search<S: AsRef<str> + Debug, S2: AsRef<str> + Debug>(
pub async fn channel_search<S: AsRef<str>, S2: AsRef<str>>(
&self,
channel_id: S,
query: S2,
@ -150,8 +143,7 @@ impl RustyPipeQuery {
}
/// Get the playlists of a channel
#[tracing::instrument(skip(self))]
pub async fn channel_playlists<S: AsRef<str> + Debug>(
pub async fn channel_playlists<S: AsRef<str>>(
&self,
channel_id: S,
) -> Result<Channel<Paginator<PlaylistItem>>, Error> {
@ -175,8 +167,7 @@ impl RustyPipeQuery {
}
/// Get additional metadata from the *About* tab of a channel
#[tracing::instrument(skip(self))]
pub async fn channel_info<S: AsRef<str> + Debug>(
pub async fn channel_info<S: AsRef<str>>(
&self,
channel_id: S,
) -> Result<Channel<ChannelInfo>, Error> {

View file

@ -1,5 +1,3 @@
use std::fmt::Debug;
use crate::{
error::{Error, ExtractionError},
model::ChannelRss,
@ -17,11 +15,7 @@ impl RustyPipeQuery {
/// for checking a lot of channels or implementing a subscription feed.
///
/// The downside of using the RSS feed is that it does not provide video durations.
#[tracing::instrument(skip(self))]
pub async fn channel_rss<S: AsRef<str> + Debug>(
&self,
channel_id: S,
) -> Result<ChannelRss, Error> {
pub async fn channel_rss<S: AsRef<str>>(&self, channel_id: S) -> Result<ChannelRss, Error> {
let channel_id = channel_id.as_ref();
let url = format!("https://www.youtube.com/feeds/videos.xml?channel_id={channel_id}");
let xml = self

View file

@ -489,7 +489,7 @@ impl RustyPipeBuilder {
.and_then(|data| match serde_json::from_str::<CacheData>(&data) {
Ok(data) => Some(data),
Err(e) => {
tracing::error!("Could not deserialize cache. Error: {}", e);
log::error!("Could not deserialize cache. Error: {}", e);
None
}
})
@ -745,7 +745,7 @@ impl RustyPipe {
// Retry in case of a recoverable status code (server err, too many requests)
if n != self.inner.n_http_retries {
let ms = util::retry_delay(n, 1000, 60000, 3);
tracing::warn!(
log::warn!(
"Retry attempt #{}. Error: {}. Waiting {} ms",
n + 1,
status,
@ -866,7 +866,7 @@ impl RustyPipe {
match desktop_client.get() {
Some(cdata) => cdata.version.clone(),
None => {
tracing::debug!("getting desktop client version");
log::debug!("getting desktop client version");
match self.extract_desktop_client_version().await {
Ok(version) => {
*desktop_client = CacheEntry::from(ClientData {
@ -877,7 +877,7 @@ impl RustyPipe {
version
}
Err(e) => {
tracing::warn!("{}, falling back to hardcoded desktop client version", e);
log::warn!("{}, falling back to hardcoded desktop client version", e);
DESKTOP_CLIENT_VERSION.to_owned()
}
}
@ -898,7 +898,7 @@ impl RustyPipe {
match music_client.get() {
Some(cdata) => cdata.version.clone(),
None => {
tracing::debug!("getting music client version");
log::debug!("getting music client version");
match self.extract_music_client_version().await {
Ok(version) => {
*music_client = CacheEntry::from(ClientData {
@ -909,7 +909,7 @@ impl RustyPipe {
version
}
Err(e) => {
tracing::warn!("{}, falling back to hardcoded music client version", e);
log::warn!("{}, falling back to hardcoded music client version", e);
DESKTOP_MUSIC_CLIENT_VERSION.to_owned()
}
}
@ -925,7 +925,7 @@ impl RustyPipe {
match deobf_data.get() {
Some(deobf_data) => Ok(deobf_data.clone()),
None => {
tracing::debug!("getting deobf data");
log::debug!("getting deobf data");
match DeobfData::extract(self.inner.http.clone(), self.inner.reporter.as_deref())
.await
@ -941,7 +941,7 @@ impl RustyPipe {
// Try to fall back to expired cache data if available, otherwise return error
match deobf_data.get_expired() {
Some(d) => {
tracing::warn!("could not get new deobf data ({e}), falling back to expired cache");
log::warn!("could not get new deobf data ({e}), falling back to expired cache");
Ok(d.clone())
}
None => Err(e),
@ -963,7 +963,7 @@ impl RustyPipe {
match serde_json::to_string(&cdata) {
Ok(data) => storage.write(&data),
Err(e) => tracing::error!("Could not serialize cache. Error: {}", e),
Err(e) => log::error!("Could not serialize cache. Error: {}", e),
}
}
}
@ -976,7 +976,7 @@ impl RustyPipe {
/// Sometimes YouTube does not set the `__Secure-YEC` cookie. In this case, the
/// visitor data is extracted from the html page.
async fn get_visitor_data(&self) -> Result<String, Error> {
tracing::debug!("getting YT visitor data");
log::debug!("getting YT visitor data");
let resp = self.inner.http.get(YOUTUBE_MUSIC_HOME_URL).send().await?;
let vdata = resp
@ -1284,7 +1284,6 @@ impl RustyPipeQuery {
let status = response.status();
let body = response.text().await?;
tracing::debug!("fetched {} bytes from YT", body.len());
let res = if status.is_client_error() || status.is_server_error() {
let error_msg = serde_json::from_str::<response::ErrorResponse>(&body)
@ -1315,11 +1314,9 @@ impl RustyPipeQuery {
}
};
tracing::debug!("mapped response");
Ok(RequestResult { res, status, body })
}
#[tracing::instrument(skip_all)]
async fn yt_request<R: DeserializeOwned + MapResponse<M> + Debug, M>(
&self,
request: &Request,
@ -1342,7 +1339,7 @@ impl RustyPipeQuery {
if n != self.client.inner.n_http_retries {
let ms = util::retry_delay(n, 1000, 60000, 3);
tracing::warn!(
log::warn!(
"Retry attempt #{}. Error: {}. Waiting {} ms",
n + 1,
err,
@ -1383,7 +1380,7 @@ impl RustyPipeQuery {
body: &B,
deobf: Option<&DeobfData>,
) -> Result<M, Error> {
tracing::debug!("getting {}({})", operation, id);
log::debug!("getting {}({})", operation, id);
let request = self
.request_builder(ctype, endpoint)
@ -1531,7 +1528,7 @@ trait MapResponse<T> {
fn validate_country(country: Country) -> Country {
if country == Country::Zz {
tracing::warn!("Country:Zz (Global) can only be used for fetching music charts, falling back to Country:Us");
log::warn!("Country:Zz (Global) can only be used for fetching music charts, falling back to Country:Us");
Country::Us
} else {
country

View file

@ -2,7 +2,6 @@ use std::borrow::Cow;
use once_cell::sync::Lazy;
use regex::Regex;
use tracing::debug;
use crate::{
client::response::url_endpoint::NavigationEndpoint,
@ -30,7 +29,7 @@ impl RustyPipeQuery {
let res = self._music_artist(artist_id, all_albums).await;
if let Err(Error::Extraction(ExtractionError::Redirect(id))) = res {
debug!("music artist {} redirects to {}", artist_id, &id);
log::debug!("music artist {} redirects to {}", artist_id, &id);
self._music_artist(&id, all_albums).await
} else {
res

View file

@ -32,7 +32,6 @@ struct FormData {
impl RustyPipeQuery {
/// Get the YouTube Music charts for a given country
#[tracing::instrument(skip(self))]
pub async fn music_charts(&self, country: Option<Country>) -> Result<MusicCharts, Error> {
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QCharts {

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt::Debug};
use std::borrow::Cow;
use serde::Serialize;
@ -38,11 +38,7 @@ struct QRadio<'a> {
impl RustyPipeQuery {
/// Get the metadata of a YouTube music track
#[tracing::instrument(skip(self))]
pub async fn music_details<S: AsRef<str> + Debug>(
&self,
video_id: S,
) -> Result<TrackDetails, Error> {
pub async fn music_details<S: AsRef<str>>(&self, video_id: S) -> Result<TrackDetails, Error> {
let video_id = video_id.as_ref();
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QMusicDetails {
@ -66,8 +62,7 @@ impl RustyPipeQuery {
/// Get the lyrics of a YouTube music track
///
/// The `lyrics_id` has to be obtained using [`RustyPipeQuery::music_details`].
#[tracing::instrument(skip(self))]
pub async fn music_lyrics<S: AsRef<str> + Debug>(&self, lyrics_id: S) -> Result<Lyrics, Error> {
pub async fn music_lyrics<S: AsRef<str>>(&self, lyrics_id: S) -> Result<Lyrics, Error> {
let lyrics_id = lyrics_id.as_ref();
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QBrowse {
@ -88,11 +83,7 @@ impl RustyPipeQuery {
/// Get related items (tracks, playlists, artists) to a YouTube Music track
///
/// The `related_id` has to be obtained using [`RustyPipeQuery::music_details`].
#[tracing::instrument(skip(self))]
pub async fn music_related<S: AsRef<str> + Debug>(
&self,
related_id: S,
) -> Result<MusicRelated, Error> {
pub async fn music_related<S: AsRef<str>>(&self, related_id: S) -> Result<MusicRelated, Error> {
let related_id = related_id.as_ref();
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QBrowse {
@ -113,8 +104,7 @@ impl RustyPipeQuery {
/// Get a YouTube Music radio (a dynamically generated playlist)
///
/// The `radio_id` can be obtained using [`RustyPipeQuery::music_artist`] to get an artist's radio.
#[tracing::instrument(skip(self))]
pub async fn music_radio<S: AsRef<str> + Debug>(
pub async fn music_radio<S: AsRef<str>>(
&self,
radio_id: S,
) -> Result<Paginator<TrackItem>, Error> {
@ -143,8 +133,7 @@ impl RustyPipeQuery {
}
/// Get a YouTube Music radio (a dynamically generated playlist) for a track
#[tracing::instrument(skip(self))]
pub async fn music_radio_track<S: AsRef<str> + Debug>(
pub async fn music_radio_track<S: AsRef<str>>(
&self,
video_id: S,
) -> Result<Paginator<TrackItem>, Error> {
@ -153,8 +142,7 @@ impl RustyPipeQuery {
}
/// Get a YouTube Music radio (a dynamically generated playlist) for a playlist
#[tracing::instrument(skip(self))]
pub async fn music_radio_playlist<S: AsRef<str> + Debug>(
pub async fn music_radio_playlist<S: AsRef<str>>(
&self,
playlist_id: S,
) -> Result<Paginator<TrackItem>, Error> {

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt::Debug};
use std::borrow::Cow;
use crate::{
error::{Error, ExtractionError},
@ -13,7 +13,6 @@ use super::{
impl RustyPipeQuery {
/// Get a list of moods and genres from YouTube Music
#[tracing::instrument(skip(self))]
pub async fn music_genres(&self) -> Result<Vec<MusicGenreItem>, Error> {
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QBrowse {
@ -32,11 +31,7 @@ impl RustyPipeQuery {
}
/// Get the playlists from a YouTube Music genre
#[tracing::instrument(skip(self))]
pub async fn music_genre<S: AsRef<str> + Debug>(
&self,
genre_id: S,
) -> Result<MusicGenre, Error> {
pub async fn music_genre<S: AsRef<str>>(&self, genre_id: S) -> Result<MusicGenre, Error> {
let genre_id = genre_id.as_ref();
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QBrowseParams {

View file

@ -10,7 +10,6 @@ use super::{response, ClientType, MapResponse, QBrowse, RustyPipeQuery};
impl RustyPipeQuery {
/// Get the new albums that were released on YouTube Music
#[tracing::instrument(skip(self))]
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 {
@ -29,7 +28,6 @@ impl RustyPipeQuery {
}
/// Get the new music videos that were released on YouTube Music
#[tracing::instrument(skip(self))]
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 {

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt::Debug};
use std::borrow::Cow;
use crate::{
error::{Error, ExtractionError},
@ -17,8 +17,7 @@ use super::{
impl RustyPipeQuery {
/// Get a playlist from YouTube Music
#[tracing::instrument(skip(self))]
pub async fn music_playlist<S: AsRef<str> + Debug>(
pub async fn music_playlist<S: AsRef<str>>(
&self,
playlist_id: S,
) -> Result<MusicPlaylist, Error> {
@ -40,11 +39,7 @@ impl RustyPipeQuery {
}
/// Get an album from YouTube Music
#[tracing::instrument(skip(self))]
pub async fn music_album<S: AsRef<str> + Debug>(
&self,
album_id: S,
) -> Result<MusicAlbum, Error> {
pub async fn music_album<S: AsRef<str>>(&self, album_id: S) -> Result<MusicAlbum, Error> {
let album_id = album_id.as_ref();
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QBrowse {

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt::Debug};
use std::borrow::Cow;
use serde::Serialize;
@ -48,11 +48,7 @@ enum Params {
impl RustyPipeQuery {
/// Search YouTube Music. Returns items from any type.
#[tracing::instrument(skip(self))]
pub async fn music_search<S: AsRef<str> + Debug>(
&self,
query: S,
) -> Result<MusicSearchResult, Error> {
pub async fn music_search<S: AsRef<str>>(&self, query: S) -> Result<MusicSearchResult, Error> {
let query = query.as_ref();
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QSearch {
@ -72,8 +68,7 @@ impl RustyPipeQuery {
}
/// Search YouTube Music tracks
#[tracing::instrument(skip(self))]
pub async fn music_search_tracks<S: AsRef<str> + Debug>(
pub async fn music_search_tracks<S: AsRef<str>>(
&self,
query: S,
) -> Result<MusicSearchFiltered<TrackItem>, Error> {
@ -81,8 +76,7 @@ impl RustyPipeQuery {
}
/// Search YouTube Music videos
#[tracing::instrument(skip(self))]
pub async fn music_search_videos<S: AsRef<str> + Debug>(
pub async fn music_search_videos<S: AsRef<str>>(
&self,
query: S,
) -> Result<MusicSearchFiltered<TrackItem>, Error> {
@ -113,8 +107,7 @@ impl RustyPipeQuery {
}
/// Search YouTube Music albums
#[tracing::instrument(skip(self))]
pub async fn music_search_albums<S: AsRef<str> + Debug>(
pub async fn music_search_albums<S: AsRef<str>>(
&self,
query: S,
) -> Result<MusicSearchFiltered<AlbumItem>, Error> {
@ -137,12 +130,10 @@ impl RustyPipeQuery {
}
/// Search YouTube Music artists
#[tracing::instrument(skip(self))]
pub async fn music_search_artists<S: AsRef<str> + Debug>(
pub async fn music_search_artists(
&self,
query: S,
query: &str,
) -> Result<MusicSearchFiltered<ArtistItem>, Error> {
let query = query.as_ref();
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
let request_body = QSearch {
context,
@ -163,8 +154,7 @@ impl RustyPipeQuery {
///
/// Playlists are filtered whether they are created by users
/// (`community=true`) or by YouTube Music (`community=false`)
#[tracing::instrument(skip(self))]
pub async fn music_search_playlists<S: AsRef<str> + Debug>(
pub async fn music_search_playlists<S: AsRef<str>>(
&self,
query: S,
community: bool,
@ -192,8 +182,7 @@ impl RustyPipeQuery {
}
/// Get YouTube Music search suggestions
#[tracing::instrument(skip(self))]
pub async fn music_search_suggestion<S: AsRef<str> + Debug>(
pub async fn music_search_suggestion<S: AsRef<str>>(
&self,
query: S,
) -> Result<MusicSearchSuggestion, Error> {

View file

@ -1,5 +1,3 @@
use std::fmt::Debug;
use crate::error::{Error, ExtractionError};
use crate::model::{
paginator::{ContinuationEndpoint, Paginator},
@ -13,8 +11,7 @@ use super::{response, ClientType, MapResponse, QContinuation, RustyPipeQuery};
impl RustyPipeQuery {
/// Get more YouTube items from the given continuation token and endpoint
#[tracing::instrument(skip(self))]
pub async fn continuation<T: FromYtItem, S: AsRef<str> + Debug>(
pub async fn continuation<T: FromYtItem, S: AsRef<str>>(
&self,
ctoken: S,
endpoint: ContinuationEndpoint,

View file

@ -1,7 +1,6 @@
use std::{
borrow::Cow,
collections::{BTreeMap, HashMap},
fmt::Debug,
};
use once_cell::sync::Lazy;
@ -62,8 +61,7 @@ struct QContentPlaybackContext<'a> {
impl RustyPipeQuery {
/// 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>>(&self, video_id: S) -> Result<VideoPlayer, Error> {
let video_id = video_id.as_ref();
let desktop_res = self.player_from_client(video_id, ClientType::Desktop).await;
@ -92,8 +90,7 @@ impl RustyPipeQuery {
}
/// Get YouTube player data (video/audio streams + basic metadata) using the specified client
#[tracing::instrument(skip(self))]
pub async fn player_from_client<S: AsRef<str> + Debug>(
pub async fn player_from_client<S: AsRef<str>>(
&self,
video_id: S,
client_type: ClientType,

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, convert::TryFrom, fmt::Debug};
use std::{borrow::Cow, convert::TryFrom};
use time::OffsetDateTime;
@ -12,8 +12,7 @@ use super::{response, ClientType, MapResponse, MapResult, QBrowse, RustyPipeQuer
impl RustyPipeQuery {
/// Get a YouTube playlist
#[tracing::instrument(skip(self))]
pub async fn playlist<S: AsRef<str> + Debug>(&self, playlist_id: S) -> Result<Playlist, Error> {
pub async fn playlist<S: AsRef<str>>(&self, playlist_id: S) -> Result<Playlist, Error> {
let playlist_id = playlist_id.as_ref();
let context = self.get_context(ClientType::Desktop, true, None).await;
let request_body = QBrowse {

View file

@ -1,5 +1,3 @@
use std::fmt::Debug;
use serde::Serialize;
use crate::{
@ -21,8 +19,7 @@ struct QSearch<'a> {
impl RustyPipeQuery {
/// Search YouTube
#[tracing::instrument(skip(self))]
pub async fn search<S: AsRef<str> + Debug>(&self, query: S) -> Result<SearchResult, Error> {
pub async fn search<S: AsRef<str>>(&self, query: S) -> Result<SearchResult, Error> {
let query = query.as_ref();
let context = self.get_context(ClientType::Desktop, true, None).await;
let request_body = QSearch {
@ -42,8 +39,7 @@ impl RustyPipeQuery {
}
/// Search YouTube using the given [`SearchFilter`]
#[tracing::instrument(skip(self))]
pub async fn search_filter<S: AsRef<str> + Debug>(
pub async fn search_filter<S: AsRef<str>>(
&self,
query: S,
filter: &SearchFilter,
@ -67,11 +63,7 @@ impl RustyPipeQuery {
}
/// Get YouTube search suggestions
#[tracing::instrument(skip(self))]
pub async fn search_suggestion<S: AsRef<str> + Debug>(
&self,
query: S,
) -> Result<Vec<String>, Error> {
pub async fn search_suggestion<S: AsRef<str>>(&self, query: S) -> Result<Vec<String>, Error> {
let url = url::Url::parse_with_params(
"https://suggestqueries-clients6.youtube.com/complete/search?client=youtube&xhr=t",
&[

View file

@ -11,7 +11,6 @@ use super::{response, ClientType, MapResponse, QBrowse, QBrowseParams, RustyPipe
impl RustyPipeQuery {
/// Get the videos from the YouTube startpage
#[tracing::instrument(skip(self))]
pub async fn startpage(&self) -> Result<Paginator<VideoItem>, Error> {
let context = self.get_context(ClientType::Desktop, true, None).await;
let request_body = QBrowse {
@ -30,7 +29,6 @@ impl RustyPipeQuery {
}
/// Get the videos from the YouTube trending page
#[tracing::instrument(skip(self))]
pub async fn trending(&self) -> Result<Vec<VideoItem>, Error> {
let context = self.get_context(ClientType::Desktop, true, None).await;
let request_body = QBrowseParams {

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt::Debug};
use std::borrow::Cow;
use serde::Serialize;
@ -59,8 +59,7 @@ impl RustyPipeQuery {
/// );
/// # });
/// ```
#[tracing::instrument(skip(self))]
pub async fn resolve_url<S: AsRef<str> + Debug>(
pub async fn resolve_url<S: AsRef<str>>(
self,
url: S,
resolve_albums: bool,
@ -237,8 +236,7 @@ impl RustyPipeQuery {
/// );
/// # });
/// ```
#[tracing::instrument(skip(self))]
pub async fn resolve_string<S: AsRef<str> + Debug>(
pub async fn resolve_string<S: AsRef<str>>(
self,
s: S,
resolve_albums: bool,

View file

@ -1,5 +1,3 @@
use std::fmt::Debug;
use serde::Serialize;
use crate::{
@ -28,11 +26,7 @@ struct QVideo<'a> {
impl RustyPipeQuery {
/// Get the metadata for a video
#[tracing::instrument(skip(self))]
pub async fn video_details<S: AsRef<str> + Debug>(
&self,
video_id: S,
) -> Result<VideoDetails, Error> {
pub async fn video_details<S: AsRef<str>>(&self, video_id: S) -> Result<VideoDetails, Error> {
let video_id = video_id.as_ref();
let context = self.get_context(ClientType::Desktop, true, None).await;
let request_body = QVideo {
@ -53,8 +47,7 @@ impl RustyPipeQuery {
}
/// Get the comments for a video using the continuation token obtained from `rusty_pipe_query.video_details()`
#[tracing::instrument(skip(self))]
pub async fn video_comments<S: AsRef<str> + Debug>(
pub async fn video_comments<S: AsRef<str>>(
&self,
ctoken: S,
visitor_data: Option<&str>,

View file

@ -29,7 +29,7 @@ impl DeobfData {
pub async fn extract(http: Client, reporter: Option<&dyn Reporter>) -> Result<Self, Error> {
let js_url = get_player_js_url(&http).await?;
let player_js = get_response(&http, &js_url).await?;
tracing::debug!("downloaded player.js from {}", js_url);
log::debug!("downloaded player.js from {}", js_url);
let res = Self::extract_fns(&js_url, &player_js);
@ -89,7 +89,7 @@ impl Deobfuscator {
res.as_str().map_or(
Err(DeobfError::Other("sig deobfuscation func returned null")),
|res| {
tracing::debug!("deobfuscated sig");
log::debug!("deobfuscated sig");
Ok(res.to_owned())
},
)
@ -102,7 +102,7 @@ impl Deobfuscator {
res.as_str().map_or(
Err(DeobfError::Other("nsig deobfuscation func returned null")),
|res| {
tracing::debug!("deobfuscated nsig");
log::debug!("deobfuscated nsig");
Ok(res.to_owned())
},
)

View file

@ -23,9 +23,9 @@ use std::{
path::{Path, PathBuf},
};
use log::error;
use serde::{Deserialize, Serialize};
use time::{macros::format_description, OffsetDateTime};
use tracing::error;
use crate::{deobfuscate::DeobfData, util};

View file

@ -32,6 +32,7 @@ use rustypipe::param::{
#[case::tv_html5_embed(ClientType::TvHtml5Embed)]
#[case::android(ClientType::Android)]
#[case::ios(ClientType::Ios)]
#[test_log::test]
fn get_player_from_client(#[case] client_type: ClientType, rp: RustyPipe) {
let player_data =
tokio_test::block_on(rp.query().player_from_client("n4tK7LYFxI0", client_type)).unwrap();
@ -1468,6 +1469,7 @@ fn music_album_not_found(rp: RustyPipe) {
#[case::no_artist("no_artist", "UCh8gHdtzO2tXd593_bjErWg", false, 0, 2)]
// querying Trailerpark's secondary YouTube channel should result in the YTM channel being fetched
#[case::secondary_channel("no_more_albums", "UCC9192yGQD25eBZgFZ84MPw", true, 15, 0)]
#[test_log::test]
fn music_artist(
#[case] name: &str,
#[case] id: &str,
@ -1489,17 +1491,12 @@ fn music_artist(
assert_gte(artist.subscriber_count.unwrap(), 30000, "subscribers");
}
artist.tracks.iter().for_each(|t| {
assert!(!t.cover.is_empty());
if t.is_video {
assert!(t.view_count.is_some());
} else {
assert!(t.album.is_some());
}
});
// Check images
assert!(!artist.header_image.is_empty(), "got no header image");
artist
.tracks
.iter()
.for_each(|t| assert!(!t.cover.is_empty()));
artist
.albums
.iter()