Compare commits

...

12 commits

61 changed files with 28570 additions and 4776 deletions

View file

@ -16,6 +16,7 @@ pub async fn download_testfiles(project_root: &Path) {
player(&testfiles).await;
player_model(&testfiles).await;
playlist(&testfiles).await;
playlist_cont(&testfiles).await;
video_details(&testfiles).await;
comments_top(&testfiles).await;
comments_latest(&testfiles).await;
@ -141,6 +142,25 @@ async fn playlist(testfiles: &Path) {
}
}
async fn playlist_cont(testfiles: &Path) {
let mut json_path = testfiles.to_path_buf();
json_path.push("playlist");
json_path.push("playlist_cont.json");
if json_path.exists() {
return;
}
let rp = RustyPipe::new();
let playlist = rp
.query()
.playlist("PL5dDx681T4bR7ZF1IuWzOv1omlRbE7PiJ")
.await
.unwrap();
let rp = rp_testfile(&json_path);
playlist.videos.next(rp.query()).await.unwrap().unwrap();
}
async fn video_details(testfiles: &Path) {
for (name, id) in [
("music", "XuM2onMGvTI"),
@ -174,9 +194,11 @@ async fn comments_top(testfiles: &Path) {
let details = rp.query().video_details("ZeerrnuLi5E").await.unwrap();
let rp = rp_testfile(&json_path);
rp.query()
.video_comments(&details.top_comments.ctoken.unwrap())
details
.top_comments
.next(rp.query())
.await
.unwrap()
.unwrap();
}
@ -192,9 +214,11 @@ async fn comments_latest(testfiles: &Path) {
let details = rp.query().video_details("ZeerrnuLi5E").await.unwrap();
let rp = rp_testfile(&json_path);
rp.query()
.video_comments(&details.latest_comments.ctoken.unwrap())
details
.latest_comments
.next(rp.query())
.await
.unwrap()
.unwrap();
}
@ -280,10 +304,7 @@ async fn channel_videos_cont(testfiles: &Path) {
.unwrap();
let rp = rp_testfile(&json_path);
rp.query()
.channel_videos_continuation(&videos.content.ctoken.unwrap())
.await
.unwrap();
videos.content.next(rp.query()).await.unwrap().unwrap();
}
async fn channel_playlists_cont(testfiles: &Path) {
@ -302,10 +323,7 @@ async fn channel_playlists_cont(testfiles: &Path) {
.unwrap();
let rp = rp_testfile(&json_path);
rp.query()
.channel_playlists_continuation(&playlists.content.ctoken.unwrap())
.await
.unwrap();
playlists.content.next(rp.query()).await.unwrap().unwrap();
}
async fn search(testfiles: &Path) {

View file

@ -3,17 +3,14 @@ use url::Url;
use crate::{
error::{Error, ExtractionError},
model::{Channel, ChannelInfo, ChannelPlaylist, ChannelVideo, Paginator},
model::{Channel, ChannelInfo, Paginator, PlaylistItem, VideoItem},
param::{ChannelOrder, Language},
serializer::MapResult,
timeago,
util::{self, TryRemove},
};
use super::{
response::{self, FromWLang},
ClientType, MapResponse, QContinuation, RustyPipeQuery, YTContext,
};
use super::{response, ClientType, MapResponse, RustyPipeQuery, YTContext};
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
@ -41,7 +38,7 @@ impl RustyPipeQuery {
pub async fn channel_videos(
self,
channel_id: &str,
) -> Result<Channel<Paginator<ChannelVideo>>, Error> {
) -> Result<Channel<Paginator<VideoItem>>, Error> {
self.channel_videos_ordered(channel_id, ChannelOrder::default())
.await
}
@ -50,7 +47,7 @@ impl RustyPipeQuery {
self,
channel_id: &str,
order: ChannelOrder,
) -> Result<Channel<Paginator<ChannelVideo>>, Error> {
) -> Result<Channel<Paginator<VideoItem>>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QChannel {
context,
@ -72,30 +69,10 @@ impl RustyPipeQuery {
.await
}
pub async fn channel_videos_continuation(
self,
ctoken: &str,
) -> Result<Paginator<ChannelVideo>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QContinuation {
context,
continuation: ctoken,
};
self.execute_request::<response::ChannelCont, _, _>(
ClientType::Desktop,
"channel_videos_continuation",
ctoken,
"browse",
&request_body,
)
.await
}
pub async fn channel_playlists(
self,
channel_id: &str,
) -> Result<Channel<Paginator<ChannelPlaylist>>, Error> {
) -> Result<Channel<Paginator<PlaylistItem>>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QChannel {
context,
@ -113,26 +90,6 @@ impl RustyPipeQuery {
.await
}
pub async fn channel_playlists_continuation(
self,
ctoken: &str,
) -> Result<Paginator<ChannelPlaylist>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QContinuation {
context,
continuation: ctoken,
};
self.execute_request::<response::ChannelCont, _, _>(
ClientType::Desktop,
"channel_playlists_continuation",
ctoken,
"browse",
&request_body,
)
.await
}
pub async fn channel_info(&self, channel_id: &str) -> Result<Channel<ChannelInfo>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QChannel {
@ -152,13 +109,13 @@ impl RustyPipeQuery {
}
}
impl MapResponse<Channel<Paginator<ChannelVideo>>> for response::Channel {
impl MapResponse<Channel<Paginator<VideoItem>>> for response::Channel {
fn map_response(
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Channel<Paginator<ChannelVideo>>>, ExtractionError> {
) -> Result<MapResult<Channel<Paginator<VideoItem>>>, ExtractionError> {
let content = map_channel_content(self.contents, id, self.alerts)?;
let grid = match content {
response::channel::ChannelContent::GridRenderer { items } => Some(items),
@ -181,20 +138,22 @@ impl MapResponse<Channel<Paginator<ChannelVideo>>> for response::Channel {
}
}
impl MapResponse<Channel<Paginator<ChannelPlaylist>>> for response::Channel {
impl MapResponse<Channel<Paginator<PlaylistItem>>> for response::Channel {
fn map_response(
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Channel<Paginator<ChannelPlaylist>>>, ExtractionError> {
) -> Result<MapResult<Channel<Paginator<PlaylistItem>>>, ExtractionError> {
let content = map_channel_content(self.contents, id, self.alerts)?;
let grid = match content {
response::channel::ChannelContent::GridRenderer { items } => Some(items),
_ => None,
};
let p_res = grid.map(map_playlists).unwrap_or_default();
let p_res = grid
.map(|item| map_playlists(item, lang))
.unwrap_or_default();
Ok(MapResult {
c: map_channel(
@ -267,98 +226,29 @@ impl MapResponse<Channel<ChannelInfo>> for response::Channel {
}
}
impl MapResponse<Paginator<ChannelVideo>> for response::ChannelCont {
fn map_response(
self,
_id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Paginator<ChannelVideo>>, ExtractionError> {
let mut actions = self.on_response_received_actions;
let res = actions
.try_swap_remove(0)
.ok_or(ExtractionError::Retry)?
.append_continuation_items_action
.continuation_items;
Ok(map_videos(res, lang))
}
}
impl MapResponse<Paginator<ChannelPlaylist>> for response::ChannelCont {
fn map_response(
self,
_id: &str,
_lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Paginator<ChannelPlaylist>>, ExtractionError> {
let mut actions = self.on_response_received_actions;
let res = actions
.try_swap_remove(0)
.ok_or(ExtractionError::Retry)?
.append_continuation_items_action
.continuation_items;
Ok(map_playlists(res))
}
}
fn map_videos(
res: MapResult<Vec<response::VideoListItem>>,
res: MapResult<Vec<response::YouTubeListItem>>,
lang: Language,
) -> MapResult<Paginator<ChannelVideo>> {
let mut ctoken = None;
let videos = res
.c
.into_iter()
.filter_map(|item| match item {
response::VideoListItem::GridVideoRenderer(video) => {
Some(ChannelVideo::from_w_lang(video, lang))
}
response::VideoListItem::RichItemRenderer {
content: response::RichItem::VideoRenderer(video),
} => Some(ChannelVideo::from_w_lang(video, lang)),
response::VideoListItem::ContinuationItemRenderer {
continuation_endpoint,
} => {
ctoken = Some(continuation_endpoint.continuation_command.token);
None
}
_ => None,
})
.collect();
) -> MapResult<Paginator<VideoItem>> {
let mut mapper = response::YouTubeListMapper::<VideoItem>::new(lang);
mapper.map_response(res);
MapResult {
c: Paginator::new(None, videos, ctoken),
warnings: res.warnings,
c: Paginator::new(None, mapper.items, mapper.ctoken),
warnings: mapper.warnings,
}
}
fn map_playlists(
res: MapResult<Vec<response::VideoListItem>>,
) -> MapResult<Paginator<ChannelPlaylist>> {
let mut ctoken = None;
let playlists = res
.c
.into_iter()
.filter_map(|item| match item {
response::VideoListItem::GridPlaylistRenderer(playlist) => Some(playlist.into()),
response::VideoListItem::RichItemRenderer {
content: response::RichItem::PlaylistRenderer(playlist),
} => Some(playlist.into()),
response::VideoListItem::ContinuationItemRenderer {
continuation_endpoint,
} => {
ctoken = Some(continuation_endpoint.continuation_command.token);
None
}
_ => None,
})
.collect();
res: MapResult<Vec<response::YouTubeListItem>>,
lang: Language,
) -> MapResult<Paginator<PlaylistItem>> {
let mut mapper = response::YouTubeListMapper::<PlaylistItem>::new(lang);
mapper.map_response(res);
MapResult {
c: Paginator::new(None, playlists, ctoken),
warnings: res.warnings,
c: Paginator::new(None, mapper.items, mapper.ctoken),
warnings: mapper.warnings,
}
}
@ -410,6 +300,7 @@ fn map_channel<T>(
.subscriber_count_text
.and_then(|txt| util::parse_large_numstr(&txt, lang)),
avatar: header.avatar.into(),
verification: header.badges.into(),
description: metadata.description,
tags: microformat.microformat_data_renderer.tags,
vanity_url,
@ -443,6 +334,7 @@ fn map_channel<T>(
.and_then(|txt| util::parse_large_numstr(txt, lang))
}),
avatar: hdata.map(|hdata| hdata.1.into()).unwrap_or_default(),
verification: crate::model::Verification::None,
description: metadata.description,
tags: microformat.microformat_data_renderer.tags,
vanity_url,
@ -516,7 +408,7 @@ mod tests {
use crate::{
client::{response, MapResponse},
model::{Channel, ChannelInfo, ChannelPlaylist, ChannelVideo, Paginator},
model::{Channel, ChannelInfo, Paginator, PlaylistItem, VideoItem},
param::Language,
serializer::MapResult,
};
@ -537,7 +429,7 @@ mod tests {
let channel: response::Channel =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Channel<Paginator<ChannelVideo>>> =
let map_res: MapResult<Channel<Paginator<VideoItem>>> =
channel.map_response(id, Language::En, None).unwrap();
assert!(
@ -557,27 +449,6 @@ mod tests {
}
}
#[test]
fn map_channel_videos_cont() {
let json_path = Path::new("testfiles/channel/channel_videos_cont.json");
let json_file = File::open(json_path).unwrap();
let channel: response::ChannelCont =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Paginator<ChannelVideo>> = channel
.map_response("UC2DjFE7Xf11URZqWBigcVOQ", Language::En, None)
.unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!("map_channel_videos_cont", map_res.c, {
".items[].publish_date" => "[date]",
});
}
#[test]
fn map_channel_playlists() {
let json_path = Path::new("testfiles/channel/channel_playlists.json");
@ -585,7 +456,7 @@ mod tests {
let channel: response::Channel =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Channel<Paginator<ChannelPlaylist>>> = channel
let map_res: MapResult<Channel<Paginator<PlaylistItem>>> = channel
.map_response("UC2DjFE7Xf11URZqWBigcVOQ", Language::En, None)
.unwrap();
@ -597,25 +468,6 @@ mod tests {
insta::assert_ron_snapshot!("map_channel_playlists", map_res.c);
}
#[test]
fn map_channel_playlists_cont() {
let json_path = Path::new("testfiles/channel/channel_playlists_cont.json");
let json_file = File::open(json_path).unwrap();
let channel: response::ChannelCont =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Paginator<ChannelPlaylist>> = channel
.map_response("UC2DjFE7Xf11URZqWBigcVOQ", Language::En, None)
.unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!("map_channel_playlists_cont", map_res.c);
}
#[test]
fn map_channel_info() {
let json_path = Path::new("testfiles/channel/channel_info.json");

View file

@ -182,7 +182,6 @@ struct RustyPipeRef {
storage: Option<Box<dyn CacheStorage>>,
reporter: Option<Box<dyn Reporter>>,
n_http_retries: u32,
n_query_retries: u32,
consent_cookie: String,
cache: CacheHolder,
default_opts: RustyPipeOpts,
@ -200,7 +199,6 @@ pub struct RustyPipeBuilder {
storage: Option<Box<dyn CacheStorage>>,
reporter: Option<Box<dyn Reporter>>,
n_http_retries: u32,
n_query_retries: u32,
user_agent: String,
default_opts: RustyPipeOpts,
}
@ -291,8 +289,7 @@ impl RustyPipeBuilder {
default_opts: RustyPipeOpts::default(),
storage: Some(Box::new(FileStorage::default())),
reporter: Some(Box::new(FileReporter::default())),
n_http_retries: 3,
n_query_retries: 2,
n_http_retries: 2,
user_agent: DEFAULT_UA.to_owned(),
}
}
@ -328,7 +325,6 @@ impl RustyPipeBuilder {
storage: self.storage,
reporter: self.reporter,
n_http_retries: self.n_http_retries,
n_query_retries: self.n_query_retries,
consent_cookie: format!(
"{}={}{}",
CONSENT_COOKIE,
@ -382,18 +378,8 @@ impl RustyPipeBuilder {
/// The waiting time is doubled for subsequent attempts (including a bit of
/// random jitter to be less predictable).
///
/// **Default value**: 3
pub fn n_http_retries(mut self, n_retries: u32) -> Self {
self.n_http_retries = n_retries;
self
}
/// Set the number of retries for YouTube API queries.
///
/// If a YouTube API requests returns invalid data, the request is repeated.
///
/// **Default value**: 2
pub fn n_query_retries(mut self, n_retries: u32) -> Self {
pub fn n_http_retries(mut self, n_retries: u32) -> Self {
self.n_http_retries = n_retries;
self
}
@ -481,7 +467,7 @@ impl RustyPipe {
/// Execute the given http request.
async fn http_request(&self, request: Request) -> Result<Response, reqwest::Error> {
let mut last_res = None;
for n in 0..self.inner.n_http_retries {
for n in 0..=self.inner.n_http_retries {
let res = self.inner.http.execute(request.try_clone().unwrap()).await;
let emsg = match &res {
Ok(response) => {
@ -974,62 +960,6 @@ impl RustyPipeQuery {
endpoint: &str,
body: &B,
deobf: Option<&Deobfuscator>,
) -> Result<M, Error> {
for n in 0..self.client.inner.n_query_retries.saturating_sub(1) {
let res = self
._try_execute_request_deobf::<R, M, B>(
ctype,
operation,
id,
endpoint,
body,
deobf,
n == 0,
)
.await;
let emsg = match res {
Ok(res) => return Ok(res),
Err(error) => match &error {
Error::Extraction(e) => match e {
ExtractionError::Deserialization(_)
| ExtractionError::InvalidData(_)
| ExtractionError::WrongResult(_)
| ExtractionError::Retry => e.to_string(),
_ => return Err(error),
},
_ => return Err(error),
},
};
warn!("{} retry attempt #{}. Error: {}.", operation, n, emsg);
}
self._try_execute_request_deobf::<R, M, B>(
ctype,
operation,
id,
endpoint,
body,
deobf,
self.client.inner.n_query_retries < 2,
)
.await
}
/// Single try of `execute_request_deobf`
#[allow(clippy::too_many_arguments)]
async fn _try_execute_request_deobf<
R: DeserializeOwned + MapResponse<M> + Debug,
M,
B: Serialize + ?Sized,
>(
&self,
ctype: ClientType,
operation: &str,
id: &str,
endpoint: &str,
body: &B,
deobf: Option<&Deobfuscator>,
report: bool,
) -> Result<M, Error> {
let request = self
.request_builder(ctype, endpoint)
@ -1049,7 +979,6 @@ impl RustyPipeQuery {
// println!("{}", &resp_str);
let create_report = |level: Level, error: Option<String>, msgs: Vec<String>| {
if report {
if let Some(reporter) = &self.client.inner.reporter {
let report = Report {
info: Default::default(),
@ -1075,7 +1004,6 @@ impl RustyPipeQuery {
reporter.report(&report);
}
}
};
if status.is_client_error() || status.is_server_error() {
@ -1115,8 +1043,7 @@ impl RustyPipeQuery {
match e {
ExtractionError::VideoUnavailable(_, _)
| ExtractionError::VideoAgeRestricted
| ExtractionError::ContentUnavailable(_)
| ExtractionError::Retry => (),
| ExtractionError::ContentUnavailable(_) => (),
_ => create_report(Level::ERR, Some(e.to_string()), Vec::new()),
}
Err(e.into())
@ -1181,8 +1108,3 @@ trait MapResponse<T> {
deobf: Option<&Deobfuscator>,
) -> Result<MapResult<T>, ExtractionError>;
}
#[cfg(test)]
mod tests {
// use super::*;
}

View file

@ -1,83 +1,92 @@
use crate::error::Error;
use crate::model::{
ChannelPlaylist, ChannelVideo, Comment, Paginator, PlaylistVideo, RecommendedVideo, SearchItem,
SearchVideo,
use crate::error::{Error, ExtractionError};
use crate::model::{Comment, Paginator, PlaylistVideo, YouTubeItem};
use crate::param::ContinuationEndpoint;
use crate::serializer::MapResult;
use crate::util::TryRemove;
use super::{response, ClientType, MapResponse, QContinuation, RustyPipeQuery};
impl RustyPipeQuery {
pub async fn continuation<T: TryFrom<YouTubeItem>>(
self,
ctoken: &str,
endpoint: ContinuationEndpoint,
visitor_data: Option<&str>,
) -> Result<Paginator<T>, Error> {
let mut context = self.get_context(ClientType::Desktop, true).await;
context.client.visitor_data = visitor_data.map(str::to_owned);
let request_body = QContinuation {
context,
continuation: ctoken,
};
use super::RustyPipeQuery;
let p = self
.execute_request::<response::Continuation, Paginator<YouTubeItem>, _>(
ClientType::Desktop,
"continuation",
ctoken,
endpoint.as_str(),
&request_body,
)
.await?;
macro_rules! paginator {
($entity_type:ty, $cont_function:path) => {
impl Paginator<$entity_type> {
pub async fn next(&self, query: RustyPipeQuery) -> Result<Option<Self>, Error> {
Ok(match &self.ctoken {
Some(ctoken) => Some($cont_function(query, ctoken).await?),
None => None,
Ok(Paginator {
count: p.count,
items: p
.items
.into_iter()
.filter_map(|item| T::try_from(item).ok())
.collect(),
ctoken: p.ctoken,
visitor_data: p.visitor_data,
endpoint,
})
}
pub async fn extend(&mut self, query: RustyPipeQuery) -> Result<bool, Error> {
match self.next(query).await {
Ok(Some(paginator)) => {
let mut items = paginator.items;
self.items.append(&mut items);
self.ctoken = paginator.ctoken;
Ok(true)
}
Ok(None) => Ok(false),
Err(e) => Err(e),
impl<T: TryFrom<YouTubeItem>> MapResponse<Paginator<T>> for response::Continuation {
fn map_response(
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Paginator<T>>, ExtractionError> {
let mut actions = self.on_response_received_actions;
let items = some_or_bail!(
actions.try_swap_remove(0),
Err(ExtractionError::InvalidData(
"no item section renderer".into()
))
)
.append_continuation_items_action
.continuation_items;
let mut mapper = response::YouTubeListMapper::<YouTubeItem>::new(lang);
mapper.map_response(items);
Ok(MapResult {
c: Paginator::new(
self.estimated_results,
mapper
.items
.into_iter()
.filter_map(|item| T::try_from(item).ok())
.collect(),
mapper.ctoken,
),
warnings: mapper.warnings,
})
}
}
pub async fn extend_pages(
&mut self,
query: RustyPipeQuery,
n_pages: usize,
) -> Result<(), Error> {
for _ in 0..n_pages {
match self.extend(query.clone()).await {
Ok(false) => break,
Err(e) => return Err(e),
_ => {}
}
}
Ok(())
}
pub async fn extend_limit(
&mut self,
query: RustyPipeQuery,
n_items: usize,
) -> Result<(), Error> {
while self.items.len() < n_items {
match self.extend(query.clone()).await {
Ok(false) => break,
Err(e) => return Err(e),
_ => {}
}
}
Ok(())
}
}
};
}
paginator!(PlaylistVideo, RustyPipeQuery::playlist_continuation);
paginator!(RecommendedVideo, RustyPipeQuery::video_recommendations);
paginator!(Comment, RustyPipeQuery::video_comments);
paginator!(ChannelVideo, RustyPipeQuery::channel_videos_continuation);
paginator!(
ChannelPlaylist,
RustyPipeQuery::channel_playlists_continuation
);
paginator!(SearchItem, RustyPipeQuery::search_continuation);
impl Paginator<SearchVideo> {
impl<T: TryFrom<YouTubeItem>> Paginator<T> {
pub async fn next(&self, query: RustyPipeQuery) -> Result<Option<Self>, Error> {
Ok(match (&self.ctoken, &self.visitor_data) {
(Some(ctoken), Some(visitor_data)) => {
Some(query.startpage_continuation(ctoken, visitor_data).await?)
}
Ok(match &self.ctoken {
Some(ctoken) => Some(
query
.continuation(ctoken, self.endpoint, self.visitor_data.as_deref())
.await?,
),
_ => None,
})
}
@ -125,3 +134,135 @@ impl Paginator<SearchVideo> {
Ok(())
}
}
impl Paginator<Comment> {
pub async fn next(&self, query: RustyPipeQuery) -> Result<Option<Self>, Error> {
Ok(match &self.ctoken {
Some(ctoken) => Some(
query
.video_comments(ctoken, self.visitor_data.as_deref())
.await?,
),
_ => None,
})
}
}
impl Paginator<PlaylistVideo> {
pub async fn next(&self, query: RustyPipeQuery) -> Result<Option<Self>, Error> {
Ok(match &self.ctoken {
Some(ctoken) => Some(query.playlist_continuation(ctoken).await?),
None => None,
})
}
}
macro_rules! paginator {
($entity_type:ty) => {
impl Paginator<$entity_type> {
pub async fn extend(&mut self, query: RustyPipeQuery) -> Result<bool, Error> {
match self.next(query).await {
Ok(Some(paginator)) => {
let mut items = paginator.items;
self.items.append(&mut items);
self.ctoken = paginator.ctoken;
Ok(true)
}
Ok(None) => Ok(false),
Err(e) => Err(e),
}
}
pub async fn extend_pages(
&mut self,
query: RustyPipeQuery,
n_pages: usize,
) -> Result<(), Error> {
for _ in 0..n_pages {
match self.extend(query.clone()).await {
Ok(false) => break,
Err(e) => return Err(e),
_ => {}
}
}
Ok(())
}
pub async fn extend_limit(
&mut self,
query: RustyPipeQuery,
n_items: usize,
) -> Result<(), Error> {
while self.items.len() < n_items {
match self.extend(query.clone()).await {
Ok(false) => break,
Err(e) => return Err(e),
_ => {}
}
}
Ok(())
}
}
};
}
paginator!(Comment);
paginator!(PlaylistVideo);
#[cfg(test)]
mod tests {
use std::{fs::File, io::BufReader, path::Path};
use rstest::rstest;
use crate::{
client::{response, MapResponse},
model::{Paginator, PlaylistItem, YouTubeItem},
param::Language,
serializer::MapResult,
};
#[rstest]
#[case("search", "search/cont")]
#[case("startpage", "trends/startpage_cont")]
#[case("recommendations", "video_details/recommendations")]
fn map_continuation_items(#[case] name: &str, #[case] path: &str) {
let filename = format!("testfiles/{}.json", path);
let json_path = Path::new(&filename);
let json_file = File::open(json_path).unwrap();
let items: response::Continuation =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Paginator<YouTubeItem>> =
items.map_response("", Language::En, None).unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!(format!("map_{}", name), map_res.c, {
".items.*.publish_date" => "[date]",
});
}
#[rstest]
#[case("channel_playlists", "channel/channel_playlists_cont")]
fn map_continuation_playlists(#[case] name: &str, #[case] path: &str) {
let filename = format!("testfiles/{}.json", path);
let json_path = Path::new(&filename);
let json_file = File::open(json_path).unwrap();
let items: response::Continuation =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Paginator<PlaylistItem>> =
items.map_response("", Language::En, None).unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!(format!("map_{}", name), map_res.c);
}
}

View file

@ -185,7 +185,9 @@ impl MapResponse<Paginator<PlaylistVideo>> for response::PlaylistCont {
_deobf: Option<&Deobfuscator>,
) -> Result<MapResult<Paginator<PlaylistVideo>>, ExtractionError> {
let mut actions = self.on_response_received_actions;
let action = actions.try_swap_remove(0).ok_or(ExtractionError::Retry)?;
let action = actions
.try_swap_remove(0)
.ok_or_else(|| ExtractionError::InvalidData("no onResponseReceivedAction".into()))?;
let (items, ctoken) =
map_playlist_items(action.append_continuation_items_action.continuation_items.c);
@ -200,30 +202,23 @@ impl MapResponse<Paginator<PlaylistVideo>> for response::PlaylistCont {
}
}
fn map_playlist_items(items: Vec<response::VideoListItem>) -> (Vec<PlaylistVideo>, Option<String>) {
fn map_playlist_items(
items: Vec<response::playlist::PlaylistItem>,
) -> (Vec<PlaylistVideo>, Option<String>) {
let mut ctoken: Option<String> = None;
let videos = items
.into_iter()
.filter_map(|it| match it {
response::VideoListItem::PlaylistVideoRenderer(video) => {
match ChannelId::try_from(video.channel) {
Ok(channel) => Some(PlaylistVideo {
id: video.video_id,
title: video.title,
length: video.length_seconds,
thumbnail: video.thumbnail.into(),
channel,
}),
Err(_) => None,
response::playlist::PlaylistItem::PlaylistVideoRenderer(video) => {
PlaylistVideo::try_from(video).ok()
}
}
response::VideoListItem::ContinuationItemRenderer {
response::playlist::PlaylistItem::ContinuationItemRenderer {
continuation_endpoint,
} => {
ctoken = Some(continuation_endpoint.continuation_command.token);
None
}
_ => None,
response::playlist::PlaylistItem::None => None,
})
.collect::<Vec<_>>();
(videos, ctoken)
@ -259,4 +254,21 @@ mod tests {
".last_update" => "[date]"
});
}
#[test]
fn map_playlist_cont() {
let json_path = Path::new("testfiles/playlist/playlist_cont.json");
let json_file = File::open(json_path).unwrap();
let playlist: response::PlaylistCont =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res = playlist.map_response("", Language::En, None).unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!("map_playlist_cont", map_res.c);
}
}

View file

@ -3,16 +3,16 @@ use serde_with::serde_as;
use serde_with::{DefaultOnError, VecSkipError};
use super::url_endpoint::NavigationEndpoint;
use super::Thumbnails;
use super::{Alert, ChannelBadge};
use super::{ContentRenderer, ContentsRenderer, VideoListItem};
use super::{ContentRenderer, ContentsRenderer};
use super::{Thumbnails, YouTubeListItem};
use crate::serializer::ignore_any;
use crate::serializer::{text::Text, MapResult, VecLogError};
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Channel {
pub(crate) struct Channel {
#[serde(default)]
#[serde_as(as = "DefaultOnError")]
pub header: Option<Header>,
@ -23,18 +23,9 @@ pub struct Channel {
pub alerts: Option<Vec<Alert>>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelCont {
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub on_response_received_actions: Vec<OnResponseReceivedAction>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Contents {
pub(crate) struct Contents {
pub two_column_browse_results_renderer: TabsRenderer,
}
@ -43,21 +34,21 @@ pub struct Contents {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TabsRenderer {
pub(crate) struct TabsRenderer {
#[serde_as(as = "VecSkipError<_>")]
pub tabs: Vec<TabRendererWrap>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TabRendererWrap {
pub(crate) struct TabRendererWrap {
pub tab_renderer: ContentRenderer<TabContent>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TabContent {
pub(crate) struct TabContent {
#[serde(default)]
#[serde_as(as = "DefaultOnError")]
pub section_list_renderer: Option<SectionListRenderer>,
@ -69,7 +60,7 @@ pub struct TabContent {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SectionListRenderer {
pub(crate) struct SectionListRenderer {
pub contents: Vec<ItemSectionRendererWrap>,
/// - **Videos**: browse-feedUC2DjFE7Xf11URZqWBigcVOQvideos (...)
/// - **Playlists**: browse-feedUC2DjFE7Xf11URZqWBigcVOQplaylists104 (...)
@ -81,9 +72,9 @@ pub struct SectionListRenderer {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RichGridRenderer {
pub(crate) struct RichGridRenderer {
#[serde_as(as = "VecLogError<_>")]
pub contents: MapResult<Vec<VideoListItem>>,
pub contents: MapResult<Vec<YouTubeListItem>>,
/// - **Videos**: browse-feedUC2DjFE7Xf11URZqWBigcVOQvideos (...)
/// - **Playlists**: browse-feedUC2DjFE7Xf11URZqWBigcVOQplaylists104 (...)
/// - **Info**: None
@ -92,17 +83,17 @@ pub struct RichGridRenderer {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSectionRendererWrap {
pub(crate) struct ItemSectionRendererWrap {
pub item_section_renderer: ContentsRenderer<ChannelContent>,
}
#[serde_as]
#[derive(Default, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ChannelContent {
pub(crate) enum ChannelContent {
GridRenderer {
#[serde_as(as = "VecLogError<_>")]
items: MapResult<Vec<VideoListItem>>,
items: MapResult<Vec<YouTubeListItem>>,
},
ChannelAboutFullMetadataRenderer(ChannelFullMetadata),
#[default]
@ -112,7 +103,7 @@ pub enum ChannelContent {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum Header {
pub(crate) enum Header {
C4TabbedHeaderRenderer(HeaderRenderer),
/// Used for special channels like YouTube Music
CarouselHeaderRenderer(ContentsRenderer<CarouselHeaderRendererItem>),
@ -121,7 +112,7 @@ pub enum Header {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HeaderRenderer {
pub(crate) struct HeaderRenderer {
/// Approximate subscriber count (e.g. `880K subscribers`), depends on language.
///
/// `None` if the subscriber count is hidden.
@ -129,8 +120,9 @@ pub struct HeaderRenderer {
pub subscriber_count_text: Option<String>,
#[serde(default)]
pub avatar: Thumbnails,
#[serde_as(as = "Option<VecSkipError<_>>")]
pub badges: Option<Vec<ChannelBadge>>,
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub badges: Vec<ChannelBadge>,
#[serde(default)]
pub banner: Thumbnails,
#[serde(default)]
@ -143,7 +135,7 @@ pub struct HeaderRenderer {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum CarouselHeaderRendererItem {
pub(crate) enum CarouselHeaderRendererItem {
#[serde(rename_all = "camelCase")]
TopicChannelDetailsRenderer {
#[serde_as(as = "Option<Text>")]
@ -157,13 +149,13 @@ pub enum CarouselHeaderRendererItem {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Metadata {
pub(crate) struct Metadata {
pub channel_metadata_renderer: ChannelMetadataRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelMetadataRenderer {
pub(crate) struct ChannelMetadataRenderer {
pub title: String,
/// Channel ID
pub external_id: String,
@ -173,13 +165,13 @@ pub struct ChannelMetadataRenderer {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Microformat {
pub(crate) struct Microformat {
pub microformat_data_renderer: MicroformatDataRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MicroformatDataRenderer {
pub(crate) struct MicroformatDataRenderer {
#[serde(default)]
pub tags: Vec<String>,
}
@ -187,7 +179,7 @@ pub struct MicroformatDataRenderer {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelFullMetadata {
pub(crate) struct ChannelFullMetadata {
#[serde_as(as = "Text")]
pub joined_date_text: String,
#[serde_as(as = "Option<Text>")]
@ -200,22 +192,8 @@ pub struct ChannelFullMetadata {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PrimaryLink {
pub(crate) struct PrimaryLink {
#[serde_as(as = "Text")]
pub title: String,
pub navigation_endpoint: NavigationEndpoint,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OnResponseReceivedAction {
pub append_continuation_items_action: AppendAction,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AppendAction {
#[serde_as(as = "VecLogError<_>")]
pub continuation_items: MapResult<Vec<VideoListItem>>,
}

View file

@ -4,7 +4,7 @@ use serde::Deserialize;
use super::Thumbnail;
#[derive(Debug, Deserialize)]
pub struct ChannelRss {
pub(crate) struct ChannelRss {
#[serde(rename = "$unflatten=yt:channelId")]
pub channel_id: String,
#[serde(rename = "$unflatten=title")]
@ -15,7 +15,7 @@ pub struct ChannelRss {
}
#[derive(Debug, Deserialize)]
pub struct Entry {
pub(crate) struct Entry {
#[serde(rename = "$unflatten=yt:videoId")]
pub video_id: String,
#[serde(rename = "$unflatten=title")]
@ -29,7 +29,7 @@ pub struct Entry {
}
#[derive(Debug, Deserialize)]
pub struct MediaGroup {
pub(crate) struct MediaGroup {
#[serde(rename = "$unflatten=media:thumbnail")]
pub thumbnail: Thumbnail,
#[serde(rename = "$unflatten=media:description")]
@ -39,7 +39,7 @@ pub struct MediaGroup {
}
#[derive(Debug, Deserialize)]
pub struct Community {
pub(crate) struct Community {
#[serde(rename = "$unflatten=media:starRating")]
pub rating: Rating,
#[serde(rename = "$unflatten=media:statistics")]
@ -47,12 +47,12 @@ pub struct Community {
}
#[derive(Debug, Deserialize)]
pub struct Rating {
pub(crate) struct Rating {
pub count: u64,
}
#[derive(Debug, Deserialize)]
pub struct Statistics {
pub(crate) struct Statistics {
pub views: u64,
}

View file

@ -1,66 +1,55 @@
pub mod channel;
pub mod player;
pub mod playlist;
pub mod playlist_music;
pub mod search;
pub mod trends;
pub mod url_endpoint;
pub mod video_details;
pub(crate) mod channel;
pub(crate) mod player;
pub(crate) mod playlist;
// pub(crate) mod playlist_music;
pub(crate) mod search;
pub(crate) mod trends;
pub(crate) mod url_endpoint;
pub(crate) mod video_details;
pub(crate) mod video_item;
pub use channel::Channel;
pub use channel::ChannelCont;
pub use player::Player;
pub use playlist::Playlist;
pub use playlist::PlaylistCont;
pub use playlist_music::PlaylistMusic;
pub use search::Search;
pub use search::SearchCont;
pub use trends::Startpage;
pub use trends::StartpageCont;
pub use trends::Trending;
pub use url_endpoint::ResolvedUrl;
pub use video_details::VideoComments;
pub use video_details::VideoDetails;
pub use video_details::VideoRecommendations;
pub(crate) use channel::Channel;
pub(crate) use player::Player;
pub(crate) use playlist::Playlist;
pub(crate) use playlist::PlaylistCont;
// pub(crate) use playlist_music::PlaylistMusic;
pub(crate) use search::Search;
pub(crate) use trends::Startpage;
pub(crate) use trends::Trending;
pub(crate) use url_endpoint::ResolvedUrl;
pub(crate) use video_details::VideoComments;
pub(crate) use video_details::VideoDetails;
pub(crate) use video_item::YouTubeListItem;
pub(crate) use video_item::YouTubeListMapper;
#[cfg(feature = "rss")]
pub mod channel_rss;
pub(crate) mod channel_rss;
#[cfg(feature = "rss")]
pub use channel_rss::ChannelRss;
pub(crate) use channel_rss::ChannelRss;
use chrono::TimeZone;
use serde::Deserialize;
use serde_with::{json::JsonString, serde_as, DefaultOnError, VecSkipError};
use serde_with::{json::JsonString, serde_as, VecSkipError};
use crate::error::ExtractionError;
use crate::model;
use crate::param::Language;
use crate::serializer::MapResult;
use crate::serializer::{
ignore_any,
text::{Text, TextComponent},
VecLogError,
};
use crate::timeago;
use crate::util::MappingError;
use crate::util::{self, TryRemove};
use crate::serializer::{text::Text, VecLogError};
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContentRenderer<T> {
pub(crate) struct ContentRenderer<T> {
pub content: T,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContentsRenderer<T> {
pub(crate) struct ContentsRenderer<T> {
#[serde(alias = "tabs")]
pub contents: Vec<T>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ThumbnailsWrap {
pub(crate) struct ThumbnailsWrap {
#[serde(default)]
pub thumbnail: Thumbnails,
}
@ -69,276 +58,47 @@ pub struct ThumbnailsWrap {
/// Not only used for thumbnails, but also for avatars and banners.
#[derive(Default, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Thumbnails {
pub(crate) struct Thumbnails {
#[serde(default)]
pub thumbnails: Vec<Thumbnail>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Thumbnail {
pub(crate) struct Thumbnail {
pub url: String,
pub width: u32,
pub height: u32,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum VideoListItem {
/// Video on channel page
GridVideoRenderer(GridVideoRenderer),
/// Video in recommendations
CompactVideoRenderer(CompactVideoRenderer),
/// Video in playlist
PlaylistVideoRenderer(PlaylistVideoRenderer),
/// Playlist on channel page
GridPlaylistRenderer(GridPlaylistRenderer),
/// Video on startpage
///
/// Seems to be currently A/B tested on the channel page,
/// as of 11.10.2022
RichItemRenderer { content: RichItem },
/// Seems to be currently A/B tested on the video details page,
/// as of 11.10.2022
ItemSectionRenderer {
#[serde_as(as = "VecLogError<_>")]
contents: MapResult<Vec<VideoListItem>>,
},
/// Continauation items are located at the end of a list
/// and contain the continuation token for progressive loading
#[serde(rename_all = "camelCase")]
ContinuationItemRenderer {
continuation_endpoint: ContinuationEndpoint,
},
/// No video list item (e.g. ad) or unimplemented item
///
/// Unimplemented:
/// - compactPlaylistRenderer (recommended playlists)
/// - compactRadioRenderer (recommended mix)
#[serde(other, deserialize_with = "ignore_any")]
None,
}
/// Video displayed on a channel page
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GridVideoRenderer {
pub video_id: String,
pub thumbnail: Thumbnails,
#[serde_as(as = "Text")]
pub title: String,
#[serde_as(as = "Option<Text>")]
pub published_time_text: Option<String>,
/// Contains `No views` if the view count is zero
#[serde_as(as = "Option<Text>")]
pub view_count_text: Option<String>,
/// Contains video length and Short/Live tag
#[serde_as(as = "VecSkipError<_>")]
pub thumbnail_overlays: Vec<TimeOverlay>,
/// Release date for upcoming videos
pub upcoming_event_data: Option<UpcomingEventData>,
}
/// Video displayed in recommendations
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CompactVideoRenderer {
pub video_id: String,
pub thumbnail: Thumbnails,
#[serde_as(as = "Text")]
pub title: String,
#[serde(rename = "shortBylineText")]
pub channel: TextComponent,
pub channel_thumbnail: Thumbnails,
/// Channel verification badge
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub owner_badges: Vec<ChannelBadge>,
#[serde_as(as = "Option<Text>")]
pub length_text: Option<String>,
/// (e.g. `11 months ago`)
#[serde_as(as = "Option<Text>")]
pub published_time_text: Option<String>,
/// Contains `No views` if the view count is zero
#[serde_as(as = "Option<Text>")]
pub view_count_text: Option<String>,
/// Badges are displayed on the video thumbnail and
/// show certain video properties (e.g. active livestream)
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub badges: Vec<VideoBadge>,
/// Contains Short/Live tag
#[serde_as(as = "VecSkipError<_>")]
pub thumbnail_overlays: Vec<TimeOverlay>,
}
/// Video displayed in search results
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoRenderer {
pub video_id: String,
pub thumbnail: Thumbnails,
#[serde_as(as = "Text")]
pub title: String,
#[serde(rename = "shortBylineText")]
pub channel: Option<TextComponent>,
pub channel_thumbnail_supported_renderers: Option<ChannelThumbnailSupportedRenderers>,
#[serde_as(as = "Option<Text>")]
pub published_time_text: Option<String>,
#[serde_as(as = "Option<Text>")]
pub length_text: Option<String>,
/// Contains `No views` if the view count is zero
#[serde_as(as = "Option<Text>")]
pub view_count_text: Option<String>,
/// Channel verification badge
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub owner_badges: Vec<ChannelBadge>,
/// Contains Short/Live tag
#[serde_as(as = "VecSkipError<_>")]
pub thumbnail_overlays: Vec<TimeOverlay>,
/// Abbreviated video description (on startpage)
#[serde_as(as = "Option<Text>")]
pub description_snippet: Option<String>,
/// Contains abbreviated video description (on search page)
#[serde_as(as = "Option<VecSkipError<_>>")]
pub detailed_metadata_snippets: Option<Vec<DetailedMetadataSnippet>>,
/// Release date for upcoming videos
pub upcoming_event_data: Option<UpcomingEventData>,
}
/// Playlist displayed in search results
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistRenderer {
pub playlist_id: String,
#[serde_as(as = "Text")]
pub title: String,
/// The first item of this list contains the playlist thumbnail,
/// subsequent items contain very small thumbnails of the next playlist videos
pub thumbnails: Vec<Thumbnails>,
#[serde_as(as = "JsonString")]
pub video_count: u64,
#[serde(rename = "shortBylineText")]
pub channel: TextComponent,
/// Channel verification badge
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub owner_badges: Vec<ChannelBadge>,
/// First 2 videos
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub videos: Vec<ChildVideoRendererWrap>,
}
/// Video displayed in a playlist
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistVideoRenderer {
pub video_id: String,
pub thumbnail: Thumbnails,
#[serde_as(as = "Text")]
pub title: String,
#[serde(rename = "shortBylineText")]
pub channel: TextComponent,
#[serde_as(as = "JsonString")]
pub length_seconds: u32,
}
/// Channel displayed in search results
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelRenderer {
pub channel_id: String,
#[serde_as(as = "Text")]
pub title: String,
pub thumbnail: Thumbnails,
/// Abbreviated channel description
///
/// Not present if the channel has no description
#[serde(default)]
#[serde_as(as = "Text")]
pub description_snippet: String,
/// Not present if the channel has no videos
#[serde_as(as = "Option<Text>")]
pub video_count_text: Option<String>,
#[serde_as(as = "Option<Text>")]
pub subscriber_count_text: Option<String>,
/// Channel verification badge
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub owner_badges: Vec<ChannelBadge>,
}
/// Playlist displayed on a channel page
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GridPlaylistRenderer {
pub playlist_id: String,
#[serde_as(as = "Text")]
pub title: String,
pub thumbnail: Thumbnails,
#[serde_as(as = "Text")]
pub video_count_short_text: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(clippy::large_enum_variant)]
pub enum RichItem {
VideoRenderer(VideoRenderer),
PlaylistRenderer(GridPlaylistRenderer),
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpcomingEventData {
/// Unixtime in seconds
#[serde_as(as = "JsonString")]
pub start_time: i64,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContinuationItemRenderer {
pub(crate) struct ContinuationItemRenderer {
pub continuation_endpoint: ContinuationEndpoint,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContinuationEndpoint {
pub(crate) struct ContinuationEndpoint {
pub continuation_command: ContinuationCommand,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContinuationCommand {
pub(crate) struct ContinuationCommand {
pub token: String,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Icon {
pub(crate) struct Icon {
pub icon_type: IconType,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum IconType {
pub(crate) enum IconType {
/// Checkmark for verified channels
Check,
/// Music note for verified artists
@ -349,151 +109,81 @@ pub enum IconType {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoOwner {
pub video_owner_renderer: VideoOwnerRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoOwnerRenderer {
pub title: TextComponent,
pub thumbnail: Thumbnails,
#[serde_as(as = "Option<Text>")]
pub subscriber_count_text: Option<String>,
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub badges: Vec<ChannelBadge>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelBadge {
pub(crate) struct ChannelBadge {
pub metadata_badge_renderer: ChannelBadgeRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelBadgeRenderer {
pub(crate) struct ChannelBadgeRenderer {
pub style: ChannelBadgeStyle,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ChannelBadgeStyle {
pub(crate) enum ChannelBadgeStyle {
BadgeStyleTypeVerified,
BadgeStyleTypeVerifiedArtist,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TimeOverlay {
pub thumbnail_overlay_time_status_renderer: TimeOverlayRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TimeOverlayRenderer {
/// `29:54`
///
/// Is `LIVE` in case of a livestream and `SHORTS` in case of a short video
#[serde_as(as = "Text")]
pub text: String,
#[serde(default)]
#[serde_as(deserialize_as = "DefaultOnError")]
pub style: TimeOverlayStyle,
}
#[derive(Default, Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum TimeOverlayStyle {
#[default]
Default,
Live,
Shorts,
}
/// Badges are displayed on the video thumbnail and
/// show certain video properties (e.g. active livestream)
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoBadge {
pub metadata_badge_renderer: VideoBadgeRenderer,
}
/// Badges are displayed on the video thumbnail and
/// show certain video properties (e.g. active livestream)
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoBadgeRenderer {
pub style: VideoBadgeStyle,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum VideoBadgeStyle {
/// Active livestream
BadgeStyleTypeLiveNow,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Alert {
pub(crate) struct Alert {
pub alert_renderer: AlertRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AlertRenderer {
pub(crate) struct AlertRenderer {
#[serde_as(as = "Text")]
pub text: String,
}
// CONTINUATION
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelThumbnailSupportedRenderers {
pub channel_thumbnail_with_link_renderer: ChannelThumbnailWithLinkRenderer,
pub(crate) struct Continuation {
/// Number of search results
#[serde_as(as = "Option<JsonString>")]
pub estimated_results: Option<u64>,
#[serde(
alias = "onResponseReceivedCommands",
alias = "onResponseReceivedEndpoints"
)]
#[serde_as(as = "VecSkipError<_>")]
pub on_response_received_actions: Vec<ContinuationActionWrap>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelThumbnailWithLinkRenderer {
pub thumbnail: Thumbnails,
pub(crate) struct ContinuationActionWrap {
pub append_continuation_items_action: ContinuationAction,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DetailedMetadataSnippet {
#[serde_as(as = "Text")]
pub snippet_text: String,
pub(crate) struct ContinuationAction {
#[serde_as(as = "VecLogError<_>")]
pub continuation_items: MapResult<Vec<YouTubeListItem>>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChildVideoRendererWrap {
pub child_video_renderer: ChildVideoRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChildVideoRenderer {
pub video_id: String,
#[serde_as(as = "Text")]
pub title: String,
#[serde_as(as = "Option<Text>")]
pub length_text: Option<String>,
pub(crate) struct ResponseContext {
pub visitor_data: Option<String>,
}
// YouTube Music
/*
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MusicItem {
pub(crate) struct MusicItem {
pub thumbnail: MusicThumbnailRenderer,
#[serde(default)]
#[serde_as(deserialize_as = "DefaultOnError")]
@ -506,28 +196,28 @@ pub struct MusicItem {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MusicThumbnailRenderer {
pub(crate) struct MusicThumbnailRenderer {
#[serde(alias = "croppedSquareThumbnailRenderer")]
pub music_thumbnail_renderer: ThumbnailsWrap,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistItemData {
pub(crate) struct PlaylistItemData {
pub video_id: String,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MusicContentsRenderer<T> {
pub(crate) struct MusicContentsRenderer<T> {
pub contents: Vec<T>,
#[serde_as(as = "Option<VecSkipError<_>>")]
pub continuations: Option<Vec<MusicContinuation>>,
}
#[derive(Debug, Deserialize)]
pub struct MusicColumn {
pub(crate) struct MusicColumn {
#[serde(
rename = "musicResponsiveListItemFlexColumnRenderer",
alias = "musicResponsiveListItemFixedColumnRenderer"
@ -537,19 +227,20 @@ pub struct MusicColumn {
#[serde_as]
#[derive(Debug, Deserialize)]
pub struct MusicColumnRenderer {
pub(crate) struct MusicColumnRenderer {
pub text: TextComponent,
}
*/
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MusicContinuation {
pub(crate) struct MusicContinuation {
pub next_continuation_data: MusicContinuationData,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MusicContinuationData {
pub(crate) struct MusicContinuationData {
pub continuation: String,
}
@ -601,39 +292,7 @@ impl From<Icon> for crate::model::Verification {
}
}
pub trait IsLive {
fn is_live(&self) -> bool;
}
pub trait IsShort {
fn is_short(&self) -> bool;
}
impl IsLive for Vec<VideoBadge> {
fn is_live(&self) -> bool {
self.iter().any(|badge| {
badge.metadata_badge_renderer.style == VideoBadgeStyle::BadgeStyleTypeLiveNow
})
}
}
impl IsLive for Vec<TimeOverlay> {
fn is_live(&self) -> bool {
self.iter().any(|overlay| {
overlay.thumbnail_overlay_time_status_renderer.style == TimeOverlayStyle::Live
})
}
}
impl IsShort for Vec<TimeOverlay> {
fn is_short(&self) -> bool {
self.iter().any(|overlay| {
overlay.thumbnail_overlay_time_status_renderer.style == TimeOverlayStyle::Shorts
})
}
}
pub fn alerts_to_err(alerts: Option<Vec<Alert>>) -> ExtractionError {
pub(crate) fn alerts_to_err(alerts: Option<Vec<Alert>>) -> ExtractionError {
match alerts {
Some(alerts) => ExtractionError::ContentUnavailable(
alerts
@ -646,234 +305,3 @@ pub fn alerts_to_err(alerts: Option<Vec<Alert>>) -> ExtractionError {
None => ExtractionError::ContentUnavailable("content not found".into()),
}
}
pub trait FromWLang<T> {
fn from_w_lang(from: T, lang: Language) -> Self;
}
pub trait TryFromWLang<T>: Sized {
fn from_w_lang(from: T, lang: Language) -> Result<Self, util::MappingError>;
}
impl FromWLang<GridVideoRenderer> for model::ChannelVideo {
fn from_w_lang(video: GridVideoRenderer, lang: Language) -> Self {
let mut toverlays = video.thumbnail_overlays;
let is_live = toverlays.is_live();
let is_short = toverlays.is_short();
let to = toverlays.try_swap_remove(0);
Self {
id: video.video_id,
title: video.title,
// Time text is `LIVE` for livestreams, so we ignore parse errors
length: to.and_then(|to| {
util::parse_video_length(&to.thumbnail_overlay_time_status_renderer.text)
}),
thumbnail: video.thumbnail.into(),
publish_date: video
.upcoming_event_data
.as_ref()
.map(|upc| {
chrono::Local.from_utc_datetime(&chrono::NaiveDateTime::from_timestamp(
upc.start_time,
0,
))
})
.or_else(|| {
video
.published_time_text
.as_ref()
.and_then(|txt| timeago::parse_timeago_to_dt(lang, txt))
}),
publish_date_txt: video.published_time_text,
view_count: video
.view_count_text
.and_then(|txt| util::parse_numeric(&txt).ok())
.unwrap_or_default(),
is_live,
is_short,
is_upcoming: video.upcoming_event_data.is_some(),
}
}
}
impl FromWLang<VideoRenderer> for model::ChannelVideo {
fn from_w_lang(video: VideoRenderer, lang: Language) -> Self {
let mut toverlays = video.thumbnail_overlays;
let is_live = toverlays.is_live();
let is_short = toverlays.is_short();
let to = toverlays.try_swap_remove(0);
Self {
id: video.video_id,
title: video.title,
// Time text is `LIVE` for livestreams, so we ignore parse errors
length: to.and_then(|to| {
util::parse_video_length(&to.thumbnail_overlay_time_status_renderer.text)
}),
thumbnail: video.thumbnail.into(),
publish_date: video
.upcoming_event_data
.as_ref()
.map(|upc| {
chrono::Local.from_utc_datetime(&chrono::NaiveDateTime::from_timestamp(
upc.start_time,
0,
))
})
.or_else(|| {
video
.published_time_text
.as_ref()
.and_then(|txt| timeago::parse_timeago_to_dt(lang, txt))
}),
publish_date_txt: video.published_time_text,
view_count: video
.view_count_text
.and_then(|txt| util::parse_numeric(&txt).ok())
.unwrap_or_default(),
is_live,
is_short,
is_upcoming: video.upcoming_event_data.is_some(),
}
}
}
impl From<GridPlaylistRenderer> for model::ChannelPlaylist {
fn from(playlist: GridPlaylistRenderer) -> Self {
Self {
id: playlist.playlist_id,
name: playlist.title,
thumbnail: playlist.thumbnail.into(),
video_count: util::parse_numeric(&playlist.video_count_short_text).ok(),
}
}
}
impl TryFromWLang<CompactVideoRenderer> for model::RecommendedVideo {
fn from_w_lang(
video: CompactVideoRenderer,
lang: Language,
) -> Result<Self, util::MappingError> {
let channel = model::ChannelId::try_from(video.channel)?;
Ok(Self {
id: video.video_id,
title: video.title,
length: video
.length_text
.and_then(|txt| util::parse_video_length(&txt)),
thumbnail: video.thumbnail.into(),
channel: model::ChannelTag {
id: channel.id,
name: channel.name,
avatar: video.channel_thumbnail.into(),
verification: video.owner_badges.into(),
subscriber_count: None,
},
publish_date: video
.published_time_text
.as_ref()
.and_then(|txt| timeago::parse_timeago_to_dt(lang, txt)),
publish_date_txt: video.published_time_text,
view_count: video
.view_count_text
.and_then(|txt| util::parse_numeric(&txt).ok())
.unwrap_or_default(),
is_live: video.badges.is_live(),
is_short: video.thumbnail_overlays.is_short(),
})
}
}
impl TryFromWLang<VideoRenderer> for model::SearchVideo {
fn from_w_lang(video: VideoRenderer, lang: Language) -> Result<Self, util::MappingError> {
let channel = model::ChannelId::try_from(
video
.channel
.ok_or_else(|| MappingError("no video channel".into()))?,
)?;
let channel_thumbnail = video
.channel_thumbnail_supported_renderers
.ok_or_else(|| MappingError("no video channel thumbnail".into()))?;
Ok(Self {
id: video.video_id,
title: video.title,
length: video
.length_text
.and_then(|txt| util::parse_video_length(&txt)),
thumbnail: video.thumbnail.into(),
channel: model::ChannelTag {
id: channel.id,
name: channel.name,
avatar: channel_thumbnail
.channel_thumbnail_with_link_renderer
.thumbnail
.into(),
verification: video.owner_badges.into(),
subscriber_count: None,
},
publish_date: video
.published_time_text
.as_ref()
.and_then(|txt| timeago::parse_timeago_to_dt(lang, txt)),
publish_date_txt: video.published_time_text,
view_count: video
.view_count_text
.and_then(|txt| util::parse_numeric(&txt).ok())
.unwrap_or_default(),
is_live: video.thumbnail_overlays.is_live(),
is_short: video.thumbnail_overlays.is_short(),
short_description: video
.detailed_metadata_snippets
.and_then(|mut snippets| snippets.try_swap_remove(0).map(|s| s.snippet_text))
.or(video.description_snippet)
.unwrap_or_default(),
})
}
}
impl From<PlaylistRenderer> for model::SearchPlaylist {
fn from(playlist: PlaylistRenderer) -> Self {
let mut thumbnails = playlist.thumbnails;
Self {
id: playlist.playlist_id,
name: playlist.title,
thumbnail: thumbnails.try_swap_remove(0).unwrap_or_default().into(),
video_count: playlist.video_count,
first_videos: playlist
.videos
.into_iter()
.map(|v| model::SearchPlaylistVideo {
id: v.child_video_renderer.video_id,
title: v.child_video_renderer.title,
length: v
.child_video_renderer
.length_text
.and_then(|txt| util::parse_video_length(&txt)),
})
.collect(),
}
}
}
impl From<ChannelRenderer> for model::SearchChannel {
fn from(channel: ChannelRenderer) -> Self {
Self {
id: channel.channel_id,
name: channel.title,
avatar: channel.thumbnail.into(),
verification: channel.owner_badges.into(),
subscriber_count: channel
.subscriber_count_text
.and_then(|txt| util::parse_numeric(&txt).ok()),
video_count: channel
.video_count_text
.and_then(|txt| util::parse_numeric(&txt).ok())
.unwrap_or_default(),
short_description: channel.description_snippet,
}
}
}

View file

@ -9,7 +9,7 @@ use crate::serializer::{text::Text, MapResult, VecLogError};
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Player {
pub(crate) struct Player {
pub playability_status: PlayabilityStatus,
pub streaming_data: Option<StreamingData>,
pub captions: Option<Captions>,
@ -18,7 +18,7 @@ pub struct Player {
#[derive(Debug, Deserialize)]
#[serde(tag = "status", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum PlayabilityStatus {
pub(crate) enum PlayabilityStatus {
#[serde(rename_all = "camelCase")]
Ok { live_streamability: Option<Empty> },
/// Video cant be played because of DRM / Geoblock
@ -35,12 +35,12 @@ pub enum PlayabilityStatus {
}
#[derive(Debug, Deserialize)]
pub struct Empty {}
pub(crate) struct Empty {}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StreamingData {
pub(crate) struct StreamingData {
#[serde_as(as = "JsonString")]
pub expires_in_seconds: u32,
#[serde(default)]
@ -58,7 +58,7 @@ pub struct StreamingData {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Format {
pub(crate) struct Format {
pub itag: u32,
pub url: Option<String>,
@ -94,8 +94,6 @@ pub struct Format {
pub audio_quality: Option<AudioQuality>,
#[serde_as(as = "Option<JsonString>")]
pub audio_sample_rate: Option<u32>,
pub audio_channels: Option<u8>,
pub loudness_db: Option<f64>,
pub audio_track: Option<AudioTrack>,
pub signature_cipher: Option<String>,
@ -119,7 +117,7 @@ impl Format {
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(rename_all = "lowercase")]
pub enum Quality {
pub(crate) enum Quality {
Tiny,
Small,
Medium,
@ -132,7 +130,7 @@ pub enum Quality {
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum AudioQuality {
pub(crate) enum AudioQuality {
#[serde(rename = "AUDIO_QUALITY_LOW", alias = "low")]
Low,
#[serde(rename = "AUDIO_QUALITY_MEDIUM", alias = "medium")]
@ -143,7 +141,7 @@ pub enum AudioQuality {
#[derive(Default, Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum FormatType {
pub(crate) enum FormatType {
#[default]
Default,
/// This stream only works via DASH and not via progressive HTTP.
@ -152,13 +150,13 @@ pub enum FormatType {
#[derive(Default, Debug, Deserialize)]
#[serde(default, rename_all = "camelCase")]
pub struct ColorInfo {
pub(crate) struct ColorInfo {
pub primaries: Primaries,
}
#[derive(Default, Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Primaries {
pub(crate) enum Primaries {
#[default]
ColorPrimariesBt709,
ColorPrimariesBt2020,
@ -166,7 +164,7 @@ pub enum Primaries {
#[derive(Default, Debug, Deserialize)]
#[serde(default, rename_all = "camelCase")]
pub struct AudioTrack {
pub(crate) struct AudioTrack {
pub id: String,
pub display_name: String,
pub audio_is_default: bool,
@ -174,20 +172,20 @@ pub struct AudioTrack {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Captions {
pub(crate) struct Captions {
pub player_captions_tracklist_renderer: PlayerCaptionsTracklistRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlayerCaptionsTracklistRenderer {
pub(crate) struct PlayerCaptionsTracklistRenderer {
pub caption_tracks: Vec<CaptionTrack>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CaptionTrack {
pub(crate) struct CaptionTrack {
pub base_url: String,
#[serde_as(as = "Text")]
pub name: String,
@ -197,7 +195,7 @@ pub struct CaptionTrack {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoDetails {
pub(crate) struct VideoDetails {
pub video_id: String,
pub title: String,
#[serde_as(as = "JsonString")]

View file

@ -1,16 +1,18 @@
use serde::Deserialize;
use serde_with::serde_as;
use serde_with::{DefaultOnError, VecSkipError};
use serde_with::{json::JsonString, serde_as, DefaultOnError, VecSkipError};
use crate::serializer::text::{Text, TextComponent};
use crate::serializer::{MapResult, VecLogError};
use crate::serializer::{ignore_any, MapResult, VecLogError};
use crate::util::MappingError;
use super::{Alert, ContentRenderer, ContentsRenderer, ThumbnailsWrap, VideoListItem};
use super::{
Alert, ContentRenderer, ContentsRenderer, ContinuationEndpoint, Thumbnails, ThumbnailsWrap,
};
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Playlist {
pub(crate) struct Playlist {
pub contents: Option<Contents>,
pub header: Option<Header>,
pub sidebar: Option<Sidebar>,
@ -21,7 +23,7 @@ pub struct Playlist {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistCont {
pub(crate) struct PlaylistCont {
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub on_response_received_actions: Vec<OnResponseReceivedAction>,
@ -29,52 +31,52 @@ pub struct PlaylistCont {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Contents {
pub(crate) struct Contents {
pub two_column_browse_results_renderer: ContentsRenderer<Tab>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Tab {
pub(crate) struct Tab {
pub tab_renderer: ContentRenderer<SectionList>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SectionList {
pub(crate) struct SectionList {
pub section_list_renderer: ContentsRenderer<ItemSection>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSection {
pub(crate) struct ItemSection {
pub item_section_renderer: ContentsRenderer<PlaylistVideoListRenderer>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistVideoListRenderer {
pub(crate) struct PlaylistVideoListRenderer {
pub playlist_video_list_renderer: PlaylistVideoList,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistVideoList {
pub(crate) struct PlaylistVideoList {
#[serde_as(as = "VecLogError<_>")]
pub contents: MapResult<Vec<VideoListItem>>,
pub contents: MapResult<Vec<PlaylistItem>>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Header {
pub(crate) struct Header {
pub playlist_header_renderer: HeaderRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HeaderRenderer {
pub(crate) struct HeaderRenderer {
pub playlist_id: String,
#[serde_as(as = "Text")]
pub title: String,
@ -93,48 +95,48 @@ pub struct HeaderRenderer {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistHeaderBanner {
pub(crate) struct PlaylistHeaderBanner {
pub hero_playlist_thumbnail_renderer: ThumbnailsWrap,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Byline {
pub(crate) struct Byline {
pub playlist_byline_renderer: BylineRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BylineRenderer {
pub(crate) struct BylineRenderer {
#[serde_as(as = "Text")]
pub text: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Sidebar {
pub(crate) struct Sidebar {
pub playlist_sidebar_renderer: SidebarRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SidebarRenderer {
pub(crate) struct SidebarRenderer {
#[serde_as(as = "VecSkipError<_>")]
pub items: Vec<SidebarItemPrimary>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SidebarItemPrimary {
pub(crate) struct SidebarItemPrimary {
pub playlist_sidebar_primary_info_renderer: SidebarPrimaryInfoRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SidebarPrimaryInfoRenderer {
pub(crate) struct SidebarPrimaryInfoRenderer {
pub thumbnail_renderer: PlaylistThumbnailRenderer,
/// - `"495", " videos"`
/// - `"3,310,996 views"`
@ -145,22 +147,70 @@ pub struct SidebarPrimaryInfoRenderer {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistThumbnailRenderer {
pub(crate) struct PlaylistThumbnailRenderer {
// the alternative field name is used by YTM playlists
#[serde(alias = "playlistCustomThumbnailRenderer")]
pub playlist_video_thumbnail_renderer: ThumbnailsWrap,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OnResponseReceivedAction {
pub(crate) enum PlaylistItem {
/// Video in playlist
PlaylistVideoRenderer(PlaylistVideoRenderer),
/// Continauation items are located at the end of a list
/// and contain the continuation token for progressive loading
#[serde(rename_all = "camelCase")]
ContinuationItemRenderer {
continuation_endpoint: ContinuationEndpoint,
},
/// No video list item (e.g. ad) or unimplemented item
#[serde(other, deserialize_with = "ignore_any")]
None,
}
/// Video displayed in a playlist
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct PlaylistVideoRenderer {
pub video_id: String,
pub thumbnail: Thumbnails,
#[serde_as(as = "Text")]
pub title: String,
#[serde(rename = "shortBylineText")]
pub channel: TextComponent,
#[serde_as(as = "JsonString")]
pub length_seconds: u32,
}
impl TryFrom<PlaylistVideoRenderer> for crate::model::PlaylistVideo {
type Error = MappingError;
fn try_from(video: PlaylistVideoRenderer) -> Result<Self, Self::Error> {
Ok(Self {
id: video.video_id,
title: video.title,
length: video.length_seconds,
thumbnail: video.thumbnail.into(),
channel: crate::model::ChannelId::try_from(video.channel)?,
})
}
}
// Continuation
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct OnResponseReceivedAction {
pub append_continuation_items_action: AppendAction,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AppendAction {
pub(crate) struct AppendAction {
#[serde_as(as = "VecLogError<_>")]
pub continuation_items: MapResult<Vec<VideoListItem>>,
pub continuation_items: MapResult<Vec<PlaylistItem>>,
}

View file

@ -11,33 +11,33 @@ use super::{
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistMusic {
pub(crate) struct PlaylistMusic {
pub contents: Contents,
pub header: Header,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Contents {
pub(crate) struct Contents {
pub single_column_browse_results_renderer: ContentsRenderer<Tab>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Tab {
pub(crate) struct Tab {
pub tab_renderer: ContentRenderer<SectionList>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SectionList {
pub(crate) struct SectionList {
/// Includes a continuation token for fetching recommendations
pub section_list_renderer: MusicContentsRenderer<ItemSection>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSection {
pub(crate) struct ItemSection {
#[serde(alias = "musicPlaylistShelfRenderer")]
pub music_shelf_renderer: MusicShelf,
}
@ -45,7 +45,7 @@ pub struct ItemSection {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MusicShelf {
pub(crate) struct MusicShelf {
/// Playlist ID (only for playlists)
pub playlist_id: Option<String>,
#[serde_as(as = "VecSkipError<_>")]
@ -57,20 +57,20 @@ pub struct MusicShelf {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaylistMusicItem {
pub(crate) struct PlaylistMusicItem {
pub music_responsive_list_item_renderer: MusicItem,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Header {
pub(crate) struct Header {
pub music_detail_header_renderer: HeaderRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HeaderRenderer {
pub(crate) struct HeaderRenderer {
#[serde_as(as = "crate::serializer::text::Text")]
pub title: String,
/// Content type + Channel/Artist + Year.

View file

@ -1,100 +1,25 @@
use serde::Deserialize;
use serde_with::json::JsonString;
use serde_with::{serde_as, VecSkipError};
use serde_with::{json::JsonString, serde_as};
use crate::serializer::ignore_any;
use crate::serializer::{text::Text, MapResult, VecLogError};
use super::{
ChannelRenderer, ContentsRenderer, ContinuationEndpoint, PlaylistRenderer, VideoRenderer,
};
use super::video_item::YouTubeListRendererWrap;
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Search {
pub(crate) struct Search {
#[serde_as(as = "Option<JsonString>")]
pub estimated_results: Option<u64>,
pub contents: Contents,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SearchCont {
#[serde_as(as = "Option<JsonString>")]
pub estimated_results: Option<u64>,
#[serde_as(as = "VecSkipError<_>")]
pub on_response_received_commands: Vec<SearchContCommand>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SearchContCommand {
pub append_continuation_items_action: SearchContAction,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SearchContAction {
pub continuation_items: Vec<SectionListItem>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Contents {
pub(crate) struct Contents {
pub two_column_search_results_renderer: TwoColumnSearchResultsRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TwoColumnSearchResultsRenderer {
pub primary_contents: PrimaryContents,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PrimaryContents {
pub section_list_renderer: ContentsRenderer<SectionListItem>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum SectionListItem {
#[serde(rename_all = "camelCase")]
ItemSectionRenderer {
#[serde_as(as = "VecLogError<_>")]
contents: MapResult<Vec<SearchItem>>,
},
/// Continuation token to fetch more search results
#[serde(rename_all = "camelCase")]
ContinuationItemRenderer {
continuation_endpoint: ContinuationEndpoint,
},
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum SearchItem {
/// Video in search results
VideoRenderer(VideoRenderer),
/// Playlist in search results
PlaylistRenderer(PlaylistRenderer),
/// Channel displayed in search results
ChannelRenderer(ChannelRenderer),
/// Corrected search query
#[serde(rename_all = "camelCase")]
ShowingResultsForRenderer {
#[serde_as(as = "Text")]
corrected_query: String,
},
/// No search result item (e.g. ad) or unimplemented item
///
/// Unimplemented:
/// - shelfRenderer (e.g. Latest from channel, For you)
#[serde(other, deserialize_with = "ignore_any")]
None,
pub(crate) struct TwoColumnSearchResultsRenderer {
pub primary_contents: YouTubeListRendererWrap,
}

View file

@ -1,133 +1,37 @@
use serde::Deserialize;
use serde_with::{serde_as, VecSkipError};
use crate::serializer::{ignore_any, MapResult, VecLogError};
use super::{ContentRenderer, ContentsRenderer, VideoListItem, VideoRenderer};
use super::{video_item::YouTubeListRendererWrap, ContentRenderer, ResponseContext};
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Startpage {
pub contents: Contents<BrowseResultsStartpage>,
pub(crate) struct Startpage {
pub contents: Contents,
pub response_context: ResponseContext,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StartpageCont {
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub on_response_received_actions: Vec<OnResponseReceivedAction>,
pub(crate) struct Trending {
pub contents: Contents,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Contents<T> {
pub two_column_browse_results_renderer: T,
pub(crate) struct Contents {
pub two_column_browse_results_renderer: BrowseResults,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BrowseResultsStartpage {
pub(crate) struct BrowseResults {
#[serde_as(as = "VecSkipError<_>")]
pub tabs: Vec<Tab<StartpageTabContent>>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BrowseResultsTrends {
#[serde_as(as = "VecSkipError<_>")]
pub tabs: Vec<Tab<TrendingTabContent>>,
pub tabs: Vec<Tab<YouTubeListRendererWrap>>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Tab<T> {
pub(crate) struct Tab<T> {
pub tab_renderer: ContentRenderer<T>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StartpageTabContent {
pub rich_grid_renderer: RichGridRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RichGridRenderer {
#[serde_as(as = "VecLogError<_>")]
pub contents: MapResult<Vec<VideoListItem>>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Trending {
pub contents: Contents<BrowseResultsTrends>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TrendingTabContent {
pub section_list_renderer: ContentsRenderer<ItemSectionRenderer>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSectionRenderer {
pub item_section_renderer: ContentsRenderer<ShelfRenderer>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ShelfRenderer {
pub shelf_renderer: ContentRenderer<ShelfContents>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ShelfContents {
pub expanded_shelf_contents_renderer: Option<ShelfContentsRenderer>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ShelfContentsRenderer {
#[serde_as(as = "VecLogError<_>")]
pub items: MapResult<Vec<TrendingListItem>>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ResponseContext {
pub visitor_data: Option<String>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(clippy::large_enum_variant)]
pub enum TrendingListItem {
VideoRenderer(VideoRenderer),
#[serde(other, deserialize_with = "ignore_any")]
None,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OnResponseReceivedAction {
pub append_continuation_items_action: AppendAction,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AppendAction {
#[serde_as(as = "VecLogError<_>")]
pub continuation_items: MapResult<Vec<VideoListItem>>,
}

View file

@ -6,14 +6,14 @@ use crate::model::UrlTarget;
/// navigation/resolve_url response model
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ResolvedUrl {
pub(crate) struct ResolvedUrl {
pub endpoint: NavigationEndpoint,
}
#[serde_as]
#[derive(Debug, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct NavigationEndpoint {
pub(crate) struct NavigationEndpoint {
#[serde(default)]
#[serde_as(deserialize_as = "DefaultOnError")]
pub watch_endpoint: Option<WatchEndpoint>,
@ -30,7 +30,7 @@ pub struct NavigationEndpoint {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WatchEndpoint {
pub(crate) struct WatchEndpoint {
pub video_id: String,
#[serde(default)]
pub start_time_seconds: u32,
@ -38,43 +38,43 @@ pub struct WatchEndpoint {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BrowseEndpoint {
pub(crate) struct BrowseEndpoint {
pub browse_id: String,
pub browse_endpoint_context_supported_configs: Option<BrowseEndpointConfig>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UrlEndpoint {
pub(crate) struct UrlEndpoint {
pub url: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BrowseEndpointConfig {
pub(crate) struct BrowseEndpointConfig {
pub browse_endpoint_context_music_config: BrowseEndpointMusicConfig,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BrowseEndpointMusicConfig {
pub(crate) struct BrowseEndpointMusicConfig {
pub page_type: PageType,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandMetadata {
pub(crate) struct CommandMetadata {
pub web_command_metadata: WebCommandMetadata,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WebCommandMetadata {
pub(crate) struct WebCommandMetadata {
pub web_page_type: PageType,
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
pub enum PageType {
pub(crate) enum PageType {
#[serde(rename = "MUSIC_PAGE_TYPE_ARTIST")]
Artist,
#[serde(rename = "MUSIC_PAGE_TYPE_ALBUM")]
@ -89,7 +89,7 @@ pub enum PageType {
}
impl PageType {
pub fn to_url_target(self, id: String) -> UrlTarget {
pub(crate) fn to_url_target(self, id: String) -> UrlTarget {
match self {
PageType::Artist => UrlTarget::Channel { id },
PageType::Album => UrlTarget::Playlist { id },

View file

@ -4,6 +4,7 @@ use serde::Deserialize;
use serde_with::serde_as;
use serde_with::{DefaultOnError, VecSkipError};
use crate::serializer::text::TextComponent;
use crate::serializer::{
ignore_any,
text::{AccessibilityText, AttributedText, Text, TextComponents},
@ -12,8 +13,9 @@ use crate::serializer::{
use super::{
url_endpoint::BrowseEndpoint, ContinuationEndpoint, ContinuationItemRenderer, Icon,
MusicContinuation, Thumbnails, VideoListItem, VideoOwner,
MusicContinuation, Thumbnails,
};
use super::{ChannelBadge, ResponseContext, YouTubeListItem};
/*
#VIDEO DETAILS
@ -23,7 +25,7 @@ use super::{
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoDetails {
pub(crate) struct VideoDetails {
/// Video metadata + recommended videos
pub contents: Option<Contents>,
/// Video ID
@ -31,18 +33,19 @@ pub struct VideoDetails {
/// Video chapters + comment section
#[serde_as(as = "VecLogError<_>")]
pub engagement_panels: MapResult<Vec<EngagementPanel>>,
pub response_context: ResponseContext,
}
/// Video details main object, contains video metadata and recommended videos
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Contents {
pub(crate) struct Contents {
pub two_column_watch_next_results: TwoColumnWatchNextResults,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TwoColumnWatchNextResults {
pub(crate) struct TwoColumnWatchNextResults {
/// Metadata about the video
pub results: VideoResultsWrap,
/// Video recommendations
@ -54,7 +57,7 @@ pub struct TwoColumnWatchNextResults {
/// Metadata about the video
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoResultsWrap {
pub(crate) struct VideoResultsWrap {
pub results: VideoResults,
}
@ -62,7 +65,7 @@ pub struct VideoResultsWrap {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoResults {
pub(crate) struct VideoResults {
#[serde_as(as = "VecLogError<_>")]
pub contents: MapResult<Vec<VideoResultsItem>>,
}
@ -71,7 +74,7 @@ pub struct VideoResults {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum VideoResultsItem {
pub(crate) enum VideoResultsItem {
#[serde(rename_all = "camelCase")]
VideoPrimaryInfoRenderer {
#[serde_as(as = "Text")]
@ -105,14 +108,14 @@ pub enum VideoResultsItem {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ViewCount {
pub(crate) struct ViewCount {
pub video_view_count_renderer: ViewCountRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ViewCountRenderer {
pub(crate) struct ViewCountRenderer {
/// View count (`232,975,196 views`)
#[serde_as(as = "Text")]
pub view_count: String,
@ -123,7 +126,7 @@ pub struct ViewCountRenderer {
/// Like/Dislike buttons
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoActions {
pub(crate) struct VideoActions {
pub menu_renderer: VideoActionsMenu,
}
@ -131,7 +134,7 @@ pub struct VideoActions {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoActionsMenu {
pub(crate) struct VideoActionsMenu {
#[serde_as(as = "VecSkipError<_>")]
pub top_level_buttons: Vec<TopLevelButton>,
}
@ -144,7 +147,7 @@ pub struct VideoActionsMenu {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TopLevelButton {
pub(crate) enum TopLevelButton {
ToggleButtonRenderer(ToggleButton),
#[serde(rename_all = "camelCase")]
SegmentedLikeDislikeButtonRenderer {
@ -155,7 +158,7 @@ pub enum TopLevelButton {
/// Like/Dislike button
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ToggleButtonWrap {
pub(crate) struct ToggleButtonWrap {
pub toggle_button_renderer: ToggleButton,
}
@ -163,7 +166,7 @@ pub struct ToggleButtonWrap {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ToggleButton {
pub(crate) struct ToggleButton {
/// Icon type: `LIKE` / `DISLIKE`
pub default_icon: Icon,
/// Number of likes (`like this video along with 4,010,156 other people`)
@ -173,11 +176,32 @@ pub struct ToggleButton {
pub accessibility_data: String,
}
/// Video channel information
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct VideoOwner {
pub video_owner_renderer: VideoOwnerRenderer,
}
/// Video channel information
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct VideoOwnerRenderer {
pub title: TextComponent,
pub thumbnail: Thumbnails,
#[serde_as(as = "Option<Text>")]
pub subscriber_count_text: Option<String>,
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub badges: Vec<ChannelBadge>,
}
/// Shows additional video metadata. Its only known use is for
/// the Creative Commonse License.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MetadataRowContainer {
pub(crate) struct MetadataRowContainer {
pub metadata_row_container_renderer: MetadataRowContainerRenderer,
}
@ -185,14 +209,14 @@ pub struct MetadataRowContainer {
/// the Creative Commonse License.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MetadataRowContainerRenderer {
pub(crate) struct MetadataRowContainerRenderer {
pub rows: Vec<MetadataRow>,
}
/// Additional video metadata item (Creative Commons License)
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MetadataRow {
pub(crate) struct MetadataRow {
pub metadata_row_renderer: MetadataRowRenderer,
}
@ -200,7 +224,7 @@ pub struct MetadataRow {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MetadataRowRenderer {
pub(crate) struct MetadataRowRenderer {
// `License`
// #[serde_as(as = "Text")]
// pub title: String,
@ -215,13 +239,13 @@ pub struct MetadataRowRenderer {
/// Contains current video ID
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CurrentVideoEndpoint {
pub(crate) struct CurrentVideoEndpoint {
pub watch_endpoint: CurrentVideoWatchEndpoint,
}
/// Contains current video ID
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CurrentVideoWatchEndpoint {
pub(crate) struct CurrentVideoWatchEndpoint {
pub video_id: String,
}
@ -232,7 +256,7 @@ pub struct CurrentVideoWatchEndpoint {
#[serde_as]
#[derive(Default, Debug, Deserialize)]
#[serde(rename_all = "kebab-case", tag = "sectionIdentifier")]
pub enum ItemSection {
pub(crate) enum ItemSection {
CommentsEntryPoint {
#[serde_as(as = "VecSkipError<_>")]
contents: Vec<ItemSectionCommentCount>,
@ -248,7 +272,7 @@ pub enum ItemSection {
/// Item section containing comment count
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSectionCommentCount {
pub(crate) struct ItemSectionCommentCount {
pub comments_entry_point_header_renderer: CommentsEntryPointHeaderRenderer,
}
@ -256,7 +280,7 @@ pub struct ItemSectionCommentCount {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentsEntryPointHeaderRenderer {
pub(crate) struct CommentsEntryPointHeaderRenderer {
#[serde_as(as = "Text")]
pub comment_count: String,
}
@ -264,14 +288,14 @@ pub struct CommentsEntryPointHeaderRenderer {
/// Item section containing comments ctoken
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSectionComments {
pub(crate) struct ItemSectionComments {
pub continuation_item_renderer: ContinuationItemRenderer,
}
/// Video recommendations
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecommendationResultsWrap {
pub(crate) struct RecommendationResultsWrap {
pub secondary_results: RecommendationResults,
}
@ -279,10 +303,10 @@ pub struct RecommendationResultsWrap {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecommendationResults {
pub(crate) struct RecommendationResults {
/// Can be `None` for age-restricted videos
#[serde_as(as = "Option<VecLogError<_>>")]
pub results: Option<MapResult<Vec<VideoListItem>>>,
pub results: Option<MapResult<Vec<YouTubeListItem>>>,
#[serde_as(as = "Option<VecSkipError<_>>")]
pub continuations: Option<Vec<MusicContinuation>>,
}
@ -291,7 +315,7 @@ pub struct RecommendationResults {
/// and the comment section.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EngagementPanel {
pub(crate) struct EngagementPanel {
pub engagement_panel_section_list_renderer: EngagementPanelRenderer,
}
@ -299,7 +323,7 @@ pub struct EngagementPanel {
/// and the comment section.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "kebab-case", tag = "targetId")]
pub enum EngagementPanelRenderer {
pub(crate) enum EngagementPanelRenderer {
/// Chapter markers
EngagementPanelMacroMarkersDescriptionChapters { content: ChapterMarkersContent },
/// Comment section (contains no comments, but the
@ -318,7 +342,7 @@ pub enum EngagementPanelRenderer {
/// Chapter markers
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChapterMarkersContent {
pub(crate) struct ChapterMarkersContent {
pub macro_markers_list_renderer: MacroMarkersListRenderer,
}
@ -326,7 +350,7 @@ pub struct ChapterMarkersContent {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MacroMarkersListRenderer {
pub(crate) struct MacroMarkersListRenderer {
#[serde_as(as = "VecLogError<_>")]
pub contents: MapResult<Vec<MacroMarkersListItem>>,
}
@ -334,7 +358,7 @@ pub struct MacroMarkersListRenderer {
/// Chapter marker
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MacroMarkersListItem {
pub(crate) struct MacroMarkersListItem {
pub macro_markers_list_item_renderer: MacroMarkersListItemRenderer,
}
@ -342,7 +366,7 @@ pub struct MacroMarkersListItem {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MacroMarkersListItemRenderer {
pub(crate) struct MacroMarkersListItemRenderer {
/// Contains chapter start time in seconds
pub on_tap: MacroMarkersListItemOnTap,
#[serde(default)]
@ -355,13 +379,13 @@ pub struct MacroMarkersListItemRenderer {
/// Contains chapter start time in seconds
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MacroMarkersListItemOnTap {
pub(crate) struct MacroMarkersListItemOnTap {
pub watch_endpoint: MacroMarkersListItemWatchEndpoint,
}
/// Contains chapter start time in seconds
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MacroMarkersListItemWatchEndpoint {
pub(crate) struct MacroMarkersListItemWatchEndpoint {
/// Chapter start time in seconds
pub start_time_seconds: u32,
}
@ -370,7 +394,7 @@ pub struct MacroMarkersListItemWatchEndpoint {
/// (contains continuation tokens for fetching top/latest comments)
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentItemSectionHeader {
pub(crate) struct CommentItemSectionHeader {
pub engagement_panel_title_header_renderer: CommentItemSectionHeaderRenderer,
}
@ -379,21 +403,14 @@ pub struct CommentItemSectionHeader {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentItemSectionHeaderRenderer {
/// Approximate comment count (e.g. `81`, `2.2K`, `705K`)
///
/// The accurate count is included in the first comment response.
///
/// Is `None` if there are no comments.
#[serde_as(as = "Option<Text>")]
pub contextual_info: Option<String>,
pub(crate) struct CommentItemSectionHeaderRenderer {
pub menu: CommentItemSectionHeaderMenu,
}
/// Comment section menu
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentItemSectionHeaderMenu {
pub(crate) struct CommentItemSectionHeaderMenu {
pub sort_filter_sub_menu_renderer: CommentItemSectionHeaderMenuRenderer,
}
@ -404,48 +421,18 @@ pub struct CommentItemSectionHeaderMenu {
/// - Latest comments
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentItemSectionHeaderMenuRenderer {
pub(crate) struct CommentItemSectionHeaderMenuRenderer {
pub sub_menu_items: Vec<CommentItemSectionHeaderMenuItem>,
}
/// Comment section menu item
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentItemSectionHeaderMenuItem {
pub(crate) struct CommentItemSectionHeaderMenuItem {
/// Continuation token for fetching comments
pub service_endpoint: ContinuationEndpoint,
}
/*
#RECOMMENDATIONS CONTINUATION
*/
/// Video recommendations continuation response
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoRecommendations {
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub on_response_received_endpoints: Vec<RecommendationsContItem>,
}
/// Video recommendations continuation
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecommendationsContItem {
pub append_continuation_items_action: AppendRecommendations,
}
/// Video recommendations continuation
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AppendRecommendations {
#[serde_as(as = "VecLogError<_>")]
pub continuation_items: MapResult<Vec<VideoListItem>>,
}
/*
#COMMENTS CONTINUATION
*/
@ -454,7 +441,7 @@ pub struct AppendRecommendations {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoComments {
pub(crate) struct VideoComments {
/// - Initial response: 2*reloadContinuationItemsCommand
/// - 1*commentsHeaderRenderer: number of comments
/// - n*commentThreadRenderer, continuationItemRenderer:
@ -465,14 +452,14 @@ pub struct VideoComments {
/// - Comment replies: appendContinuationItemsAction
/// - n*commentRenderer, continuationItemRenderer:
/// replies + continuation
#[serde_as(as = "Option<VecLogError<_>>")]
pub on_response_received_endpoints: Option<MapResult<Vec<CommentsContItem>>>,
#[serde_as(as = "VecLogError<_>")]
pub on_response_received_endpoints: MapResult<Vec<CommentsContItem>>,
}
/// Video comments continuation
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentsContItem {
pub(crate) struct CommentsContItem {
#[serde(alias = "reloadContinuationItemsCommand")]
pub append_continuation_items_action: AppendComments,
}
@ -481,7 +468,7 @@ pub struct CommentsContItem {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AppendComments {
pub(crate) struct AppendComments {
#[serde_as(as = "VecLogError<_>")]
pub continuation_items: MapResult<Vec<CommentListItem>>,
}
@ -489,7 +476,7 @@ pub struct AppendComments {
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum CommentListItem {
pub(crate) enum CommentListItem {
/// Top-level comment
#[serde(rename_all = "camelCase")]
CommentThreadRenderer {
@ -519,14 +506,14 @@ pub enum CommentListItem {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Comment {
pub(crate) struct Comment {
pub comment_renderer: CommentRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentRenderer {
pub(crate) struct CommentRenderer {
/// Author name
///
/// There may be comments with missing authors (possibly deleted users?)
@ -557,13 +544,13 @@ pub struct CommentRenderer {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorEndpoint {
pub(crate) struct AuthorEndpoint {
pub browse_endpoint: BrowseEndpoint,
}
#[derive(Default, Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum CommentPriority {
pub(crate) enum CommentPriority {
/// Default rendering priority
#[default]
RenderingPriorityUnknown,
@ -575,7 +562,7 @@ pub enum CommentPriority {
/// for fetching them.
#[derive(Default, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Replies {
pub(crate) struct Replies {
pub comment_replies_renderer: RepliesRenderer,
}
@ -584,7 +571,7 @@ pub struct Replies {
#[serde_as]
#[derive(Default, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RepliesRenderer {
pub(crate) struct RepliesRenderer {
#[serde_as(as = "VecSkipError<_>")]
pub contents: Vec<CommentListItem>,
}
@ -593,7 +580,7 @@ pub struct RepliesRenderer {
/// Contains the CreatorHeart.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentActionButtons {
pub(crate) struct CommentActionButtons {
pub comment_action_buttons_renderer: CommentActionButtonsRenderer,
}
@ -601,7 +588,7 @@ pub struct CommentActionButtons {
/// Contains the CreatorHeart.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentActionButtonsRenderer {
pub(crate) struct CommentActionButtonsRenderer {
pub like_button: ToggleButtonWrap,
pub creator_heart: Option<CreatorHeart>,
}
@ -609,27 +596,27 @@ pub struct CommentActionButtonsRenderer {
/// Video creators can endorse comments by marking them with a ❤️.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreatorHeart {
pub(crate) struct CreatorHeart {
pub creator_heart_renderer: CreatorHeartRenderer,
}
/// Video creators can endorse comments by marking them with a ❤️.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreatorHeartRenderer {
pub(crate) struct CreatorHeartRenderer {
pub is_hearted: bool,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorCommentBadge {
pub(crate) struct AuthorCommentBadge {
pub author_comment_badge_renderer: AuthorCommentBadgeRenderer,
}
/// YouTube channel badge (verified) of the comment author
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorCommentBadgeRenderer {
pub(crate) struct AuthorCommentBadgeRenderer {
/// Verified: `CHECK`
///
/// Artist: `OFFICIAL_ARTIST_BADGE`

View file

@ -0,0 +1,507 @@
use chrono::TimeZone;
use serde::Deserialize;
use serde_with::{json::JsonString, serde_as, DefaultOnError, VecSkipError};
use super::{ChannelBadge, ContinuationEndpoint, Thumbnails};
use crate::{
model::{ChannelId, ChannelItem, ChannelTag, PlaylistItem, VideoItem, YouTubeItem},
param::Language,
serializer::{
ignore_any,
text::{Text, TextComponent},
MapResult, VecLogError,
},
timeago,
util::{self, TryRemove},
};
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) enum YouTubeListItem {
#[serde(alias = "gridVideoRenderer", alias = "compactVideoRenderer")]
VideoRenderer(VideoRenderer),
#[serde(alias = "gridPlaylistRenderer")]
PlaylistRenderer(PlaylistRenderer),
ChannelRenderer(ChannelRenderer),
/// Continauation items are located at the end of a list
/// and contain the continuation token for progressive loading
#[serde(rename_all = "camelCase")]
ContinuationItemRenderer {
continuation_endpoint: ContinuationEndpoint,
},
/// Corrected search query
#[serde(rename_all = "camelCase")]
ShowingResultsForRenderer {
#[serde_as(as = "Text")]
corrected_query: String,
},
/// Contains video on startpage
///
/// Seems to be currently A/B tested on the channel page,
/// as of 11.10.2022
#[serde(alias = "shelfRenderer")]
RichItemRenderer {
content: Box<YouTubeListItem>,
},
/// Contains search results
///
/// Seems to be currently A/B tested on the video details page,
/// as of 11.10.2022
#[serde(alias = "expandedShelfContentsRenderer")]
ItemSectionRenderer {
#[serde(alias = "items")]
#[serde_as(as = "VecLogError<_>")]
contents: MapResult<Vec<YouTubeListItem>>,
},
/// No video list item (e.g. ad) or unimplemented item
///
/// Unimplemented:
/// - compactPlaylistRenderer (recommended playlists)
/// - compactRadioRenderer (recommended mix)
#[serde(other, deserialize_with = "ignore_any")]
None,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct VideoRenderer {
pub video_id: String,
pub thumbnail: Thumbnails,
#[serde_as(as = "Text")]
pub title: String,
#[serde(rename = "shortBylineText")]
pub channel: Option<TextComponent>,
pub channel_thumbnail: Option<Thumbnails>,
pub channel_thumbnail_supported_renderers: Option<ChannelThumbnailSupportedRenderers>,
#[serde_as(as = "Option<Text>")]
pub published_time_text: Option<String>,
#[serde_as(as = "Option<Text>")]
pub length_text: Option<String>,
/// Contains `No views` if the view count is zero
#[serde_as(as = "Option<Text>")]
pub view_count_text: Option<String>,
/// Channel verification badge
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub owner_badges: Vec<ChannelBadge>,
/// Contains live tag for recommended videos
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub badges: Vec<VideoBadge>,
/// Contains Short/Live tag
#[serde_as(as = "VecSkipError<_>")]
pub thumbnail_overlays: Vec<TimeOverlay>,
/// Abbreviated video description (on startpage)
#[serde_as(as = "Option<Text>")]
pub description_snippet: Option<String>,
/// Contains abbreviated video description (on search page)
#[serde_as(as = "Option<VecSkipError<_>>")]
pub detailed_metadata_snippets: Option<Vec<DetailedMetadataSnippet>>,
/// Release date for upcoming videos
pub upcoming_event_data: Option<UpcomingEventData>,
}
/// Playlist displayed in search results
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct PlaylistRenderer {
pub playlist_id: String,
#[serde_as(as = "Text")]
pub title: String,
pub thumbnail: Option<Thumbnails>,
/// Used by playlists from search page
///
/// The first item of this list contains the playlist thumbnail,
/// subsequent items contain very small thumbnails of the next playlist videos
pub thumbnails: Option<Vec<Thumbnails>>,
#[serde_as(as = "Option<JsonString>")]
pub video_count: Option<u64>,
#[serde_as(as = "Option<Text>")]
pub video_count_short_text: Option<String>,
#[serde(rename = "shortBylineText")]
pub channel: Option<TextComponent>,
/// Channel verification badge
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub owner_badges: Vec<ChannelBadge>,
}
/// Channel displayed in search results
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ChannelRenderer {
pub channel_id: String,
#[serde_as(as = "Text")]
pub title: String,
pub thumbnail: Thumbnails,
/// Abbreviated channel description
///
/// Not present if the channel has no description
#[serde(default)]
#[serde_as(as = "Text")]
pub description_snippet: String,
/// Not present if the channel has no videos
#[serde_as(as = "Option<Text>")]
pub video_count_text: Option<String>,
#[serde_as(as = "Option<Text>")]
pub subscriber_count_text: Option<String>,
/// Channel verification badge
#[serde(default)]
#[serde_as(as = "VecSkipError<_>")]
pub owner_badges: Vec<ChannelBadge>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct YouTubeListRendererWrap {
#[serde(alias = "richGridRenderer")]
pub section_list_renderer: YouTubeListRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct YouTubeListRenderer {
#[serde_as(as = "VecLogError<_>")]
pub contents: MapResult<Vec<YouTubeListItem>>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct UpcomingEventData {
/// Unixtime in seconds
#[serde_as(as = "JsonString")]
pub start_time: i64,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct TimeOverlay {
pub thumbnail_overlay_time_status_renderer: TimeOverlayRenderer,
}
/// Badges are displayed on the video thumbnail and
/// show certain video properties (e.g. active livestream)
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct VideoBadge {
pub metadata_badge_renderer: VideoBadgeRenderer,
}
/// Badges are displayed on the video thumbnail and
/// show certain video properties (e.g. active livestream)
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct VideoBadgeRenderer {
pub style: VideoBadgeStyle,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub(crate) enum VideoBadgeStyle {
/// Active livestream
BadgeStyleTypeLiveNow,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct TimeOverlayRenderer {
/// `29:54`
///
/// Is `LIVE` in case of a livestream and `SHORTS` in case of a short video
#[serde_as(as = "Text")]
pub text: String,
#[serde(default)]
#[serde_as(deserialize_as = "DefaultOnError")]
pub style: TimeOverlayStyle,
}
#[derive(Default, Clone, Copy, Debug, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub(crate) enum TimeOverlayStyle {
#[default]
Default,
Live,
Shorts,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct DetailedMetadataSnippet {
#[serde_as(as = "Text")]
pub snippet_text: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ChannelThumbnailSupportedRenderers {
pub channel_thumbnail_with_link_renderer: ChannelThumbnailWithLinkRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ChannelThumbnailWithLinkRenderer {
pub thumbnail: Thumbnails,
}
trait IsLive {
fn is_live(&self) -> bool;
}
trait IsShort {
fn is_short(&self) -> bool;
}
impl IsLive for Vec<VideoBadge> {
fn is_live(&self) -> bool {
self.iter().any(|badge| {
badge.metadata_badge_renderer.style == VideoBadgeStyle::BadgeStyleTypeLiveNow
})
}
}
impl IsLive for Vec<TimeOverlay> {
fn is_live(&self) -> bool {
self.iter().any(|overlay| {
overlay.thumbnail_overlay_time_status_renderer.style == TimeOverlayStyle::Live
})
}
}
impl IsShort for Vec<TimeOverlay> {
fn is_short(&self) -> bool {
self.iter().any(|overlay| {
overlay.thumbnail_overlay_time_status_renderer.style == TimeOverlayStyle::Shorts
})
}
}
/// Result of mapping a list of different YouTube enities
/// (videos, channels, playlists)
#[derive(Debug)]
pub(crate) struct YouTubeListMapper<T> {
lang: Language,
pub items: Vec<T>,
pub warnings: Vec<String>,
pub ctoken: Option<String>,
pub corrected_query: Option<String>,
}
impl<T> YouTubeListMapper<T> {
pub fn new(lang: Language) -> Self {
Self {
lang,
items: Vec::new(),
warnings: Vec::new(),
ctoken: None,
corrected_query: None,
}
}
fn map_video(&self, video: VideoRenderer) -> VideoItem {
let mut tn_overlays = video.thumbnail_overlays;
let length_text = video.length_text.or_else(|| {
tn_overlays
.try_swap_remove(0)
.map(|overlay| overlay.thumbnail_overlay_time_status_renderer.text)
});
VideoItem {
id: video.video_id,
title: video.title,
length: length_text.and_then(|txt| util::parse_video_length(&txt)),
thumbnail: video.thumbnail.into(),
channel: video.channel.and_then(|c| {
ChannelId::try_from(c).ok().map(|c| ChannelTag {
id: c.id,
name: c.name,
avatar: video
.channel_thumbnail_supported_renderers
.map(|tn| tn.channel_thumbnail_with_link_renderer.thumbnail)
.or(video.channel_thumbnail)
.unwrap_or_default()
.into(),
verification: video.owner_badges.into(),
subscriber_count: None,
})
}),
publish_date: video
.upcoming_event_data
.as_ref()
.map(|upc| {
chrono::Local.from_utc_datetime(&chrono::NaiveDateTime::from_timestamp(
upc.start_time,
0,
))
})
.or_else(|| {
video
.published_time_text
.as_ref()
.and_then(|txt| timeago::parse_timeago_to_dt(self.lang, txt))
}),
publish_date_txt: video.published_time_text,
view_count: video
.view_count_text
.map(|txt| util::parse_numeric(&txt).unwrap_or_default()),
is_live: tn_overlays.is_live() || video.badges.is_live(),
is_short: tn_overlays.is_short(),
is_upcoming: video.upcoming_event_data.is_some(),
short_description: video
.detailed_metadata_snippets
.and_then(|mut snippets| snippets.try_swap_remove(0).map(|s| s.snippet_text))
.or(video.description_snippet),
}
}
fn map_playlist(playlist: PlaylistRenderer) -> PlaylistItem {
PlaylistItem {
id: playlist.playlist_id,
name: playlist.title,
thumbnail: playlist
.thumbnail
.or_else(|| playlist.thumbnails.and_then(|mut t| t.try_swap_remove(0)))
.unwrap_or_default()
.into(),
channel: playlist.channel.and_then(|c| {
ChannelId::try_from(c).ok().map(|c| ChannelTag {
id: c.id,
name: c.name,
avatar: Vec::new(),
verification: playlist.owner_badges.into(),
subscriber_count: None,
})
}),
video_count: playlist.video_count.or_else(|| {
playlist
.video_count_short_text
.and_then(|txt| util::parse_numeric(&txt).ok())
}),
}
}
fn map_channel(channel: ChannelRenderer) -> ChannelItem {
ChannelItem {
id: channel.channel_id,
name: channel.title,
avatar: channel.thumbnail.into(),
verification: channel.owner_badges.into(),
subscriber_count: channel
.subscriber_count_text
.and_then(|txt| util::parse_numeric(&txt).ok()),
video_count: channel
.video_count_text
.and_then(|txt| util::parse_numeric(&txt).ok())
.unwrap_or_default(),
short_description: channel.description_snippet,
}
}
}
impl YouTubeListMapper<YouTubeItem> {
fn map_item(&mut self, item: YouTubeListItem) {
match item {
YouTubeListItem::VideoRenderer(video) => {
self.items.push(YouTubeItem::Video(self.map_video(video)));
}
YouTubeListItem::PlaylistRenderer(playlist) => self
.items
.push(YouTubeItem::Playlist(Self::map_playlist(playlist))),
YouTubeListItem::ChannelRenderer(channel) => {
self.items
.push(YouTubeItem::Channel(Self::map_channel(channel)));
}
YouTubeListItem::ContinuationItemRenderer {
continuation_endpoint,
} => self.ctoken = Some(continuation_endpoint.continuation_command.token),
YouTubeListItem::ShowingResultsForRenderer { corrected_query } => {
self.corrected_query = Some(corrected_query);
}
YouTubeListItem::RichItemRenderer { content } => {
self.map_item(*content);
}
YouTubeListItem::ItemSectionRenderer { mut contents } => {
self.warnings.append(&mut contents.warnings);
contents.c.into_iter().for_each(|it| self.map_item(it));
}
YouTubeListItem::None => {}
}
}
pub(crate) fn map_response(&mut self, mut res: MapResult<Vec<YouTubeListItem>>) {
self.warnings.append(&mut res.warnings);
res.c.into_iter().for_each(|item| self.map_item(item));
}
}
impl YouTubeListMapper<VideoItem> {
fn map_item(&mut self, item: YouTubeListItem) {
match item {
YouTubeListItem::VideoRenderer(video) => {
self.items.push(self.map_video(video));
}
YouTubeListItem::ContinuationItemRenderer {
continuation_endpoint,
} => self.ctoken = Some(continuation_endpoint.continuation_command.token),
YouTubeListItem::ShowingResultsForRenderer { corrected_query } => {
self.corrected_query = Some(corrected_query);
}
YouTubeListItem::RichItemRenderer { content } => {
self.map_item(*content);
}
YouTubeListItem::ItemSectionRenderer { mut contents } => {
self.warnings.append(&mut contents.warnings);
contents.c.into_iter().for_each(|it| self.map_item(it));
}
_ => {}
}
}
pub(crate) fn map_response(&mut self, mut res: MapResult<Vec<YouTubeListItem>>) {
self.warnings.append(&mut res.warnings);
res.c.into_iter().for_each(|item| self.map_item(item));
}
}
impl YouTubeListMapper<PlaylistItem> {
fn map_item(&mut self, item: YouTubeListItem) {
match item {
YouTubeListItem::PlaylistRenderer(playlist) => {
self.items.push(Self::map_playlist(playlist))
}
YouTubeListItem::ContinuationItemRenderer {
continuation_endpoint,
} => self.ctoken = Some(continuation_endpoint.continuation_command.token),
YouTubeListItem::ShowingResultsForRenderer { corrected_query } => {
self.corrected_query = Some(corrected_query);
}
YouTubeListItem::RichItemRenderer { content } => {
self.map_item(*content);
}
YouTubeListItem::ItemSectionRenderer { mut contents } => {
self.warnings.append(&mut contents.warnings);
contents.c.into_iter().for_each(|it| self.map_item(it));
}
_ => {}
}
}
pub(crate) fn map_response(&mut self, mut res: MapResult<Vec<YouTubeListItem>>) {
self.warnings.append(&mut res.warnings);
res.c.into_iter().for_each(|item| self.map_item(item));
}
}

View file

@ -3,15 +3,11 @@ use serde::{de::IgnoredAny, Serialize};
use crate::{
deobfuscate::Deobfuscator,
error::{Error, ExtractionError},
model::{Paginator, SearchItem, SearchResult, SearchVideo},
model::{Paginator, SearchResult, YouTubeItem},
param::{search_filter::SearchFilter, Language},
util::TryRemove,
};
use super::{
response::{self, TryFromWLang},
ClientType, MapResponse, MapResult, QContinuation, RustyPipeQuery, YTContext,
};
use super::{response, ClientType, MapResponse, MapResult, RustyPipeQuery, YTContext};
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
@ -63,23 +59,6 @@ impl RustyPipeQuery {
.await
}
pub async fn search_continuation(self, ctoken: &str) -> Result<Paginator<SearchItem>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QContinuation {
context,
continuation: ctoken,
};
self.execute_request::<response::SearchCont, _, _>(
ClientType::Desktop,
"search_continuation",
ctoken,
"search",
&request_body,
)
.await
}
pub async fn search_suggestion(self, query: &str) -> Result<Vec<String>, Error> {
let url = url::Url::parse_with_params("https://suggestqueries-clients6.youtube.com/complete/search?client=youtube&gs_rn=64&gs_ri=youtube&ds=yt&cp=1&gs_id=4&xhr=t&xssi=t",
&[("hl", self.opts.lang.to_string()), ("gl", self.opts.country.to_string()), ("q", query.to_string())]
@ -114,135 +93,33 @@ impl MapResponse<SearchResult> for response::Search {
lang: Language,
_deobf: Option<&Deobfuscator>,
) -> Result<MapResult<SearchResult>, ExtractionError> {
let section_list_items = self
let items = self
.contents
.two_column_search_results_renderer
.primary_contents
.section_list_renderer
.contents;
let (items, ctoken) = map_section_list_items(section_list_items)?;
let mut warnings = items.warnings;
let (mut mapped, corrected_query) = map_search_items(items.c, lang);
warnings.append(&mut mapped.warnings);
let mut mapper = response::YouTubeListMapper::<YouTubeItem>::new(lang);
mapper.map_response(items);
Ok(MapResult {
c: SearchResult {
items: Paginator::new(self.estimated_results, mapped.c, ctoken),
corrected_query,
items: Paginator::new(self.estimated_results, mapper.items, mapper.ctoken),
corrected_query: mapper.corrected_query,
},
warnings,
warnings: mapper.warnings,
})
}
}
impl MapResponse<Paginator<SearchItem>> for response::SearchCont {
fn map_response(
self,
_id: &str,
lang: Language,
_deobf: Option<&Deobfuscator>,
) -> Result<MapResult<Paginator<SearchItem>>, ExtractionError> {
let mut commands = self.on_response_received_commands;
let cont_command = some_or_bail!(
commands.try_swap_remove(0),
Err(ExtractionError::InvalidData(
"no item section renderer".into()
))
);
let (items, ctoken) = map_section_list_items(
cont_command
.append_continuation_items_action
.continuation_items,
)?;
let mut warnings = items.warnings;
let (mut mapped, _) = map_search_items(items.c, lang);
warnings.append(&mut mapped.warnings);
Ok(MapResult {
c: Paginator::new(self.estimated_results, mapped.c, ctoken),
warnings,
})
}
}
fn map_section_list_items(
section_list_items: Vec<response::search::SectionListItem>,
) -> Result<(MapResult<Vec<response::search::SearchItem>>, Option<String>), ExtractionError> {
let mut items = None;
let mut ctoken = None;
section_list_items.into_iter().for_each(|item| match item {
response::search::SectionListItem::ItemSectionRenderer { contents } => {
items = Some(contents);
}
response::search::SectionListItem::ContinuationItemRenderer {
continuation_endpoint,
} => {
ctoken = Some(continuation_endpoint.continuation_command.token);
}
});
let items = some_or_bail!(
items,
Err(ExtractionError::InvalidData(
"no item section renderer".into()
))
);
Ok((items, ctoken))
}
fn map_search_items(
items: Vec<response::search::SearchItem>,
lang: Language,
) -> (MapResult<Vec<SearchItem>>, Option<String>) {
let mut warnings = Vec::new();
let mut c_query = None;
let mapped_items = items
.into_iter()
.filter_map(|item| match item {
response::search::SearchItem::VideoRenderer(video) => {
match SearchVideo::from_w_lang(video, lang) {
Ok(video) => Some(SearchItem::Video(video)),
Err(e) => {
warnings.push(e.to_string());
None
}
}
}
response::search::SearchItem::PlaylistRenderer(playlist) => {
Some(SearchItem::Playlist(playlist.into()))
}
response::search::SearchItem::ChannelRenderer(channel) => {
Some(SearchItem::Channel(channel.into()))
}
response::search::SearchItem::ShowingResultsForRenderer { corrected_query } => {
c_query = Some(corrected_query);
None
}
response::search::SearchItem::None => None,
})
.collect();
(
MapResult {
c: mapped_items,
warnings,
},
c_query,
)
}
#[cfg(test)]
mod tests {
use std::{fs::File, io::BufReader, path::Path};
use crate::{
client::{response, MapResponse},
model::{Paginator, SearchItem, SearchResult},
model::SearchResult,
param::Language,
serializer::MapResult,
};
@ -271,26 +148,4 @@ mod tests {
".items.items.*.publish_date" => "[date]",
});
}
#[test]
fn t_map_search_cont() {
let filename = format!("testfiles/search/cont.json");
let json_path = Path::new(&filename);
let json_file = File::open(json_path).unwrap();
let search_cont: response::SearchCont =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Paginator<SearchItem>> =
search_cont.map_response("", Language::En, None).unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!("map_search_cont", map_res.c, {
".items.*.publish_date" => "[date]",
});
}
}

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: Verified,
description: "NO SCRIPT, NO FEAR, ALL OPINION\nAn off-the-cuff Video Blog about Electronics Engineering, for engineers, hobbyists, enthusiasts, hackers and Makers\nHosted by Dave Jones from Sydney Australia\n\nDONATIONS:\nBitcoin: 3KqyH1U3qrMPnkLufM2oHDU7YB4zVZeFyZ\nEthereum: 0x99ccc4d2654ba40744a1f678d9868ecb15e91206\nPayPal: david@alternatezone.com\n\nPatreon: https://www.patreon.com/eevblog\n\nEEVblog2: http://www.youtube.com/EEVblog2\nEEVdiscover: https://www.youtube.com/channel/UCkGvUEt8iQLmq3aJIMjT2qQ\n\nEMAIL:\nAdvertising/Commercial: eevblog+business@gmail.com\nFan mail: eevblog+fan@gmail.com\nHate Mail: eevblog+hate@gmail.com\n\nI DON\'T DO PAID VIDEO SPONSORSHIPS, DON\'T ASK!\n\nPLEASE:\nDo NOT ask for personal advice on something, post it in the EEVblog forum.\nI read ALL email, but please don\'t be offended if I don\'t have time to reply, I get a LOT of email.\n\nMailbag\nPO Box 7949\nBaulkham Hills NSW 2153\nAUSTRALIA",
tags: [
"electronics",

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: Verified,
description: "NO SCRIPT, NO FEAR, ALL OPINION\nAn off-the-cuff Video Blog about Electronics Engineering, for engineers, hobbyists, enthusiasts, hackers and Makers\nHosted by Dave Jones from Sydney Australia\n\nDONATIONS:\nBitcoin: 3KqyH1U3qrMPnkLufM2oHDU7YB4zVZeFyZ\nEthereum: 0x99ccc4d2654ba40744a1f678d9868ecb15e91206\nPayPal: david@alternatezone.com\n\nPatreon: https://www.patreon.com/eevblog\n\nEEVblog2: http://www.youtube.com/EEVblog2\nEEVdiscover: https://www.youtube.com/channel/UCkGvUEt8iQLmq3aJIMjT2qQ\n\nEMAIL:\nAdvertising/Commercial: eevblog+business@gmail.com\nFan mail: eevblog+fan@gmail.com\nHate Mail: eevblog+hate@gmail.com\n\nI DON\'T DO PAID VIDEO SPONSORSHIPS, DON\'T ASK!\n\nPLEASE:\nDo NOT ask for personal advice on something, post it in the EEVblog forum.\nI read ALL email, but please don\'t be offended if I don\'t have time to reply, I get a LOT of email.\n\nMailbag\nPO Box 7949\nBaulkham Hills NSW 2153\nAUSTRALIA",
tags: [
"electronics",
@ -144,7 +145,7 @@ Channel(
content: Paginator(
count: None,
items: [
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtOV3AEwhuea4TnviddKfAj",
name: "MacGyver Project",
thumbnail: [
@ -154,9 +155,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(2),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHuvHE5GQrQJxWXHdmW2l5IF",
name: "Calculators",
thumbnail: [
@ -166,9 +168,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHs6wRwVSaErU0BEnLiHfnKJ",
name: "BM235",
thumbnail: [
@ -178,9 +181,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(9),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHu4k0ZkKFLsysSB5iava6Qu",
name: "Vibration Measurement",
thumbnail: [
@ -190,9 +194,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(2),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtdQF-m5UFZ5GEjABadI3kI",
name: "Component Selection",
thumbnail: [
@ -202,9 +207,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(4),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtlndPUSOPgsujUdq1c5Mr9",
name: "Solar Roadways",
thumbnail: [
@ -214,9 +220,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(18),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvD6M_7WeN071OVsZFE0_q-",
name: "Electronics Tutorials - AC Theory Series",
thumbnail: [
@ -226,9 +233,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(3),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtVLq2MDPIz82BWMIZcuwhK",
name: "Electronics Tutorial - DC Fundamentals",
thumbnail: [
@ -238,9 +246,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(8),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvIDfW3x2p4BY6l4RYgfBJE",
name: "Oscilloscope Probing",
thumbnail: [
@ -250,9 +259,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(13),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHu6Jjb8U82eKQfvKhJVl0Bu",
name: "Thermal Design",
thumbnail: [
@ -262,9 +272,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(9),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHs-X2Awg33PCBNrP2BGFVhC",
name: "Electric Cars",
thumbnail: [
@ -274,9 +285,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(7),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHuLODLTeq3PM-OJRP2nzNUa",
name: "Designing a better uCurrent",
thumbnail: [
@ -286,9 +298,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(3),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtvTKP4RTNW1-08Kmzy1pvA",
name: "EMC Compliance & Measurement",
thumbnail: [
@ -298,9 +311,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(8),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHuUTpCrTVX7BdU68l2aVqMv",
name: "Power Counter Display Project",
thumbnail: [
@ -310,9 +324,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(2),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvm120Tq40nKrM5SUBlolN3",
name: "Live - Ask Dave",
thumbnail: [
@ -322,9 +337,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(3),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHsiF93KOLoF1KAHArmIW9lC",
name: "Padauk Microcontroller",
thumbnail: [
@ -334,9 +350,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(10),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvxTzBLwUFw4My4rtrNFzED",
name: "Other Debunking Videos",
thumbnail: [
@ -346,9 +363,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHt2pJ7X5tumuM4Wa3r1OC7Q",
name: "Audio & Speakers",
thumbnail: [
@ -358,9 +376,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(9),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtX7OearWdmqGzqiu4DHKWi",
name: "Cameras",
thumbnail: [
@ -370,9 +389,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(16),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHu-TaNRp27_PiXjBG5wY9Gv",
name: "Cryptocurrency",
thumbnail: [
@ -382,9 +402,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(7),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvmK-VGcZ33ZuATmcNB8tvH",
name: "LCD Tutorial",
thumbnail: [
@ -394,9 +415,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(6),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvbV8x_bWQBKEg4IshWjG3U",
name: "Guest Videos",
thumbnail: [
@ -406,9 +428,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(12),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHs5tuhiqdxQeegsLDP7TM8V",
name: "Software Development",
thumbnail: [
@ -418,9 +441,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHu328BlpUOUDsv9Kf1Ri8Tg",
name: "John Kenny - Keysight",
thumbnail: [
@ -430,9 +454,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(5),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvj_E5KUBluJJupXmideiZk",
name: "General Tech Information",
thumbnail: [
@ -442,9 +467,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(2),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHsWHPg1KlSd8agKbrcn3Dwn",
name: "Microscope",
thumbnail: [
@ -454,9 +480,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(4),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHuQb5djEVLzwBSTT27p2dXB",
name: "The Signal Path",
thumbnail: [
@ -466,9 +493,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHstMIbtLqlEiidVjj8ob0xp",
name: "Thermal Imaging",
thumbnail: [
@ -478,9 +506,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(2),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHugqRHdt46SN9Bmoh-D5Gp2",
name: "EEVacademy",
thumbnail: [
@ -490,9 +519,10 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(9),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtqqYM7ON99sbyiokMKrwwI",
name: "Brainstorming",
thumbnail: [
@ -502,9 +532,11 @@ Channel(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
],
ctoken: Some("4qmFsgLCARIYVUMyRGpGRTdYZjExVVJacVdCaWdjVk9RGnRFZ2x3YkdGNWJHbHpkSE1ZQXlBQk1BRTRBZW9EUEVOblRrUlJhbEZUU2tKSmFWVkZlREpVTW5oVVdsZG9UMlJJVmtsa1NFWjRWMVV3TTFRd05EVlBXRTVwWlZkc2RtRXdNVXhqYm1RelUxTm5PQSUzRCUzRJoCL2Jyb3dzZS1mZWVkVUMyRGpGRTdYZjExVVJacVdCaWdjVk9RcGxheWxpc3RzMTA0"),
endpoint: browse,
),
)

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: Verified,
description: "Hi, Im Tina, aka Doobydobap!\n\nFood is the medium I use to tell stories and connect with people who share the same passion as I do. Whether its because youre hungry at midnight or trying to learn how to cook, I hope you enjoy watching my content and recipes. Don\'t yuck my yum!\n\nwww.doobydobap.com\n",
tags: [],
vanity_url: Some("https://www.youtube.com/c/Doobydobap"),
@ -115,7 +116,7 @@ Channel(
content: Paginator(
count: None,
items: [
ChannelVideo(
VideoItem(
id: "EIcmfSzeaKk",
title: "our new normal",
length: Some(1106),
@ -141,14 +142,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("9 hours ago"),
view_count: 142423,
view_count: Some(142423),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("I\'ve been really enjoying cooking more lately (′ꈍωꈍ‵)\nWas so cool to see my makgeolli fermenting, I can\'t wait to show you the progress update in my next vlog. \n\nThank you again doobies!..."),
),
ChannelVideo(
VideoItem(
id: "9NuhKCv3crg",
title: "the end.",
length: Some(982),
@ -174,14 +177,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 days ago"),
view_count: 989763,
view_count: Some(989763),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("or the start of something new~~~~~\n\nThank you for your patience on the vlog, it took some time to adjust to my new normal. Excited for change and I\'ll always try my best to make the best content..."),
),
ChannelVideo(
VideoItem(
id: "38Gd6TdmNVs",
title: "KOREAN BARBECUE l doob gourmand ep.3",
length: Some(525),
@ -207,14 +212,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 355470,
view_count: Some(355470),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("I haven\'t done a doob gourmand series in so so long! I hope you enjoyed it, let me know what kind of food you\'re interested in seeing in these series! :)\n\nLove you doobies!\n\nInstagram @doobydobap..."),
),
ChannelVideo(
VideoItem(
id: "l9TiwunjzgA",
title: "long distance",
length: Some(1043),
@ -240,14 +247,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 697188,
view_count: Some(697188),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("exciting changes are about to come! \ndoob gourmand kbbq coming out on Thursday this week :)\n\nInstagram @doobydobap \nJoin my discord! 😈\nhttps://discord.gg/doobyverse\nwww.doobydobap.com for..."),
),
ChannelVideo(
VideoItem(
id: "pRVSdUxdsVw",
title: "Repairing...",
length: Some(965),
@ -273,14 +282,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 weeks ago"),
view_count: 529586,
view_count: Some(529586),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("The word repair stems from the Latin word reparare, from re- back and parare make ready.\' And I feel that\'s exactly how I feel about this week\'s vlog-- I feel like I\'m repairing my..."),
),
ChannelVideo(
VideoItem(
id: "2FJVhdOO0F0",
title: "a health scare",
length: Some(1238),
@ -306,14 +317,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 1066729,
view_count: Some(1066729),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("https://www.nationalbreastcancer.org/about-breast-cancer/\nI\'m really thankful that my results came out okay. This really was one of the worst / scariest weeks of my life, but an important one..."),
),
ChannelVideo(
VideoItem(
id: "CutR_1SDDzY",
title: "feels good to be back",
length: Some(1159),
@ -339,14 +352,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 525663,
view_count: Some(525663),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("I missed you guys. Happy to see you guys back. \nI\'ve really been working on my mental health, educating myself with different food cultures, and focusing on being happy the last month. \nThank..."),
),
ChannelVideo(
VideoItem(
id: "KUz7oArksR4",
title: "running away",
length: Some(1023),
@ -372,14 +387,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 717806,
view_count: Some(717806),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("for now... more adventures to come! \n\n\n\n\nMusic by Mark Generous - A Summer Day - https://thmatc.co/?l=CF6C5FFF\nInstagram @doobydobap \nJoin my discord! 😈\nhttps://discord.gg/doobyverse\nwww.doobyd..."),
),
ChannelVideo(
VideoItem(
id: "sPb2gyN-hnE",
title: "worth fighting for",
length: Some(1232),
@ -405,14 +422,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 624673,
view_count: Some(624673),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Please be respectful in the comments section! \nI will not be tolerating any hateful/derogatory speech 👹👹👹 *barking noise*\n\nMusic \nMarie - Howard Harper-Barnes\nMusic by Monét Ngo -..."),
),
ChannelVideo(
VideoItem(
id: "PXsK9-CFoH4",
title: "waiting...",
length: Some(1455),
@ -438,14 +457,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 924135,
view_count: Some(924135),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("👀☂\u{fe0f}🕴\u{fe0f}\ntuna kimchi jook \n2 cups cooked rice \n3 cups water \n1 cup kimchi \n320g canned tuna \n1 tbsp perilla seed oil \n1 onion\n1 tbsp gochujang\n1 tbsp soy sauce \n½ tsp salt (to taste)..."),
),
ChannelVideo(
VideoItem(
id: "r2ye6zW0nbM",
title: "a wedding",
length: Some(1207),
@ -471,14 +492,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 1053353,
view_count: Some(1053353),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Ginger Pork Recipe!\nhttps://doobydobap.com/recipe/ginger-pork-shogayaki\n-\nInstagram @doobydobap \nJoin my discord! 😈\nhttps://discord.gg/doobyverse\nwww.doobydobap.com for recipes & stories..."),
),
ChannelVideo(
VideoItem(
id: "rriwHj8U664",
title: "my seoul apartment tour",
length: Some(721),
@ -504,14 +527,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 697242,
view_count: Some(697242),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Korea has an interesting rent structure called junseh where you pay a higher security deposit in turn for lower rent! And before anyone starts accusing me, no, it\'s all with my own money!!!..."),
),
ChannelVideo(
VideoItem(
id: "FKJtrUeol3o",
title: "with quantity comes quality",
length: Some(1140),
@ -537,14 +562,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 1086097,
view_count: Some(1086097),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("A busy, but calm week for me here in Seoul living alone. \nPlanning on exploring more parts of Korea, please let me know in the comments what you\'d wanna see!\n\nFried Eggplants with Doubanjiang..."),
),
ChannelVideo(
VideoItem(
id: "zYHB38UlzE0",
title: "Q&A l relationships, burnout, privilege, college advice, living alone, and life after youtube?",
length: Some(775),
@ -570,14 +597,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 528979,
view_count: Some(528979),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("So many questions I wasn\'t able to answer, but if you comment below I\'ll try and answer every single one of them!!!!\n\nA little bit of audio issues, it was my first time using this mic, \nsowwy..."),
),
ChannelVideo(
VideoItem(
id: "hGbQ2WM9nOo",
title: "Why does everything bad for you taste good ㅣ CHILI OIL RAMEN",
length: Some(428),
@ -603,14 +632,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 1036890,
view_count: Some(1036890),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("https://partner.bokksu.com/doobydobap use code DOOBYDOBAP to get $15 off your first bokksu order! \n\nInstagram @doobydobap \nJoin my discord! 😈\nhttps://discord.gg/doobyverse\nwww.doobydobap.com..."),
),
ChannelVideo(
VideoItem(
id: "PxGmP4v_A38",
title: "Alone and Thriving l late night korean convenience store, muji kitchenware haul, spring cleaning!",
length: Some(1437),
@ -636,14 +667,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 832542,
view_count: Some(832542),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("I could palpably feel how I\'m so much happier than before when I was reviewing my footage 🥺🥺🥺 \n\nAll the finalized recipes will be updated on my Instagram or my website! \n\nMusic\nMusic..."),
),
ChannelVideo(
VideoItem(
id: "8t-WyYcpEDE",
title: "What I hate most",
length: Some(61),
@ -669,14 +702,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 1342882,
view_count: Some(1342882),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("#shorts #cooking \nhttps://doobydobap.com/recipe/ginger-pork-shogayaki\n\nInstagram @doobydobap \nJoin my discord! 😈\nhttps://discord.gg/doobyverse\nwww.doobydobap.com for recipes & stories"),
),
ChannelVideo(
VideoItem(
id: "RroYpLxxNjY",
title: "I\'m Back. ㅣ cooking korean food, eating alone, working out, and 2M!",
length: Some(1313),
@ -702,14 +737,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 1076848,
view_count: Some(1076848),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Annyoung doobies! It has been a while since I\'ve sat down and spoken to you all. I\'m thrilled to be back, and I finally feel like I\'m in my element after a much-needed break. \n\nThank you so..."),
),
ChannelVideo(
VideoItem(
id: "l47QuudsZ34",
title: "We ate our way through Florence (ft. mamadooby)",
length: Some(1109),
@ -735,14 +772,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("5 months ago"),
view_count: 562349,
view_count: Some(562349),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Annyoung doobies :)\nI\'m back after a hiatus, I\'ve been travelling and putting my mental health first so I don\'t burn out!!! Much needed break to be inspired & grow for more content to come!..."),
),
ChannelVideo(
VideoItem(
id: "1VW7iXRIrc8",
title: "Alone, in the City of Love",
length: Some(1875),
@ -768,14 +807,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 531938,
view_count: Some(531938),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("I know it\'s a little long, but I hope you enjoyed this Paris vlog :}\n\nLocation📍\nUdon Restaurant: Sanukiya\n9 Rue d\'Argenteuil, Paris\nCoffee: Telescope Cafe\n5 Rue Villédo, 75001 Paris, France..."),
),
ChannelVideo(
VideoItem(
id: "6c58-749p6Y",
title: "Old Friends & New",
length: Some(774),
@ -801,14 +842,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 426469,
view_count: Some(426469),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Realized I have a typo that says perogis instead of peroni oop \nBut for real, I\'m so thankful for Bobbi bc she was one of the few/ only people that welcomed me to a new school/country where..."),
),
ChannelVideo(
VideoItem(
id: "Q2G53LuEUaU",
title: "Where we stand",
length: Some(858),
@ -834,14 +877,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 448915,
view_count: Some(448915),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Thank you to BetterHelp for sponsoring this video! \nGo to https://www.betterhelp.com/doobydobap to get 10% off your first month :)\n\nLocations 📍\nThis is Dover btw\nhttps://www.google.com/maps/plac..."),
),
ChannelVideo(
VideoItem(
id: "8rAOeowNQrI",
title: "That\'s so last year",
length: Some(1286),
@ -867,14 +912,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 675443,
view_count: Some(675443),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Location 📍\nScience Museum\nhttps://goo.gl/maps/dPPSZwmSrMzhEh9Y7\nNatural History Museum \nhttps://goo.gl/maps/XSu2EZN9XP8rGVWg6\nJoy King Lau - Dim Sum \nhttps://goo.gl/maps/D3rgoN1raQocyQPM6..."),
),
ChannelVideo(
VideoItem(
id: "0RGIdIKkbSI",
title: "The Muffin Man",
length: Some(1052),
@ -900,14 +947,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 426465,
view_count: Some(426465),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Use code DOOBYDOBAP16 for up to 16 FREE MEALS + 3 Surprise Gifts across 6 HelloFresh boxes plus free shipping at https://bit.ly/3Kiz0qb!\n\nMusic\nindolore - je rêve d\'é ( moow edit ) https://soundc..."),
),
ChannelVideo(
VideoItem(
id: "NudTbo2CJMY",
title: "Flying to London",
length: Some(1078),
@ -933,14 +982,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 1137831,
view_count: Some(1137831),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Tomato Beef Curry\n1 packet Japanese Curry Roux\n250g thinly sliced beef \n2 large onions\n2 tbsp butter\n2 tbsp neutral oil \n1 can whole tomatoes\n500mL water\n2 tbsp ketchup \n\n1. Melt 1 tbsp butter..."),
),
ChannelVideo(
VideoItem(
id: "8mJk1ncGZig",
title: "(not so) Teenage Angst",
length: Some(1376),
@ -966,14 +1017,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 612275,
view_count: Some(612275),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Again, I hope you guys know that my vlogs are a visual diary of whats happening in my life and what Im feeling that week. Im not speaking for everyone, so take with a grain o salt!..."),
),
ChannelVideo(
VideoItem(
id: "qvgCi2WpbfE",
title: "can\'t smell :s",
length: Some(875),
@ -999,14 +1052,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 396397,
view_count: Some(396397),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Kimchi Jeon \nParmesan Kimchi Jeon or regular, both works\nIngredients\n* 1 cup kimchi + 2 tbsp juice\n* 1 tsp gochujang (optional for extra heat)\n* ⅓ cup parmesan, grated + extra parmesan for..."),
),
ChannelVideo(
VideoItem(
id: "Sm4Yqtqr9f8",
title: "I have covid",
length: Some(814),
@ -1032,14 +1087,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 599030,
view_count: Some(599030),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("I had a bit too much fun with the intro.\nI actually didn\'t realize I shot it in slow-mo. \nThank you all for the supportive messages, donno what I did to deserve you all. Eternally thankful...."),
),
ChannelVideo(
VideoItem(
id: "ZRtf4ksF3qs",
title: "Everything I ate in Busan & make up tutorial??",
length: Some(1026),
@ -1065,14 +1122,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 530192,
view_count: Some(530192),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("I\'m okay btw!! I got overwhelmed a bit this past weekend in Busan and was really... anxious the entire time I was on my trip :(\nI\'ll still be sharing where I went from last weekend soon as..."),
),
ChannelVideo(
VideoItem(
id: "oG4Wth1oVBQ",
title: "On the other side",
length: Some(1592),
@ -1098,14 +1157,17 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("8 months ago"),
view_count: 567604,
view_count: Some(567604),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Gochujang Pasta Recipe Link\nhttps://doobydobap.com/recipe/gochujang-pasta-with-prawns\nI just didn\'t put any prawns bc I didn\'t have any!\n\nLocation\ndanil seoul \n66-33 Wangsimni-ro, Seongsu-dong..."),
),
],
ctoken: Some("4qmFsgKhARIYVUNoOGdIZHR6TzJ0WGQ1OTNfYmpFcldnGoQBOGdaZ0dsNTZYQXBZQ2pCRlozTkpiRXRwYURZdFNGZG9ZbVZuUVZObmVVMUJSVFJJYTBsTVExQlFVbXR3YjBkRlMwUnBkVmRhU1VGV1FVRVNKRFl6TkRnd056Wm1MVEF3TURBdE1tRXhaUzA0TnpRNUxXUTBaalUwTjJZNE16a3pZeGdC"),
endpoint: browse,
),
)

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: Verified,
description: "NO SCRIPT, NO FEAR, ALL OPINION\nAn off-the-cuff Video Blog about Electronics Engineering, for engineers, hobbyists, enthusiasts, hackers and Makers\nHosted by Dave Jones from Sydney Australia\n\nDONATIONS:\nBitcoin: 3KqyH1U3qrMPnkLufM2oHDU7YB4zVZeFyZ\nEthereum: 0x99ccc4d2654ba40744a1f678d9868ecb15e91206\nPayPal: david@alternatezone.com\n\nPatreon: https://www.patreon.com/eevblog\n\nEEVblog2: http://www.youtube.com/EEVblog2\nEEVdiscover: https://www.youtube.com/channel/UCkGvUEt8iQLmq3aJIMjT2qQ\n\nEMAIL:\nAdvertising/Commercial: eevblog+business@gmail.com\nFan mail: eevblog+fan@gmail.com\nHate Mail: eevblog+hate@gmail.com\n\nI DON\'T DO PAID VIDEO SPONSORSHIPS, DON\'T ASK!\n\nPLEASE:\nDo NOT ask for personal advice on something, post it in the EEVblog forum.\nI read ALL email, but please don\'t be offended if I don\'t have time to reply, I get a LOT of email.\n\nMailbag\nPO Box 7949\nBaulkham Hills NSW 2153\nAUSTRALIA",
tags: [
"electronics",
@ -144,7 +145,7 @@ Channel(
content: Paginator(
count: None,
items: [
ChannelVideo(
VideoItem(
id: "4EcQYK_no5M",
title: "EEVblog 1506 - History of Electricity with Kathy Loves Physics",
length: Some(6143),
@ -170,14 +171,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 day ago"),
view_count: 8813,
view_count: Some(8813),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Talking about the history of electricity and physics with Kathy Joseph from Kathey Loves Physics, and her new book:\nThe Lightning Tamers: True Stories of the Dreamers and Schemers Who Harnessed..."),
),
ChannelVideo(
VideoItem(
id: "zEzjVUzNAFA",
title: "EEVblog 1505 - 120W Home Phantom Power? Audit Time!",
length: Some(1464),
@ -203,14 +206,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 days ago"),
view_count: 48599,
view_count: Some(48599),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("My home takes 120W phantom standby power. Let\'s do a complete audit and see what is consuming the most power, and how it can be reduced.\n\nHow bad product design kills the environment: https://www.y..."),
),
ChannelVideo(
VideoItem(
id: "YIbQ3nudCA0",
title: "EEVblog 1504 - The COOL thing you MISSED at Tesla AI Day 2022",
length: Some(1021),
@ -236,14 +241,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("10 days ago"),
view_count: 74126,
view_count: Some(74126),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("A very cool bit of electronics failure mode analysis that you missed at the 2022 Tesla AI Day presentation. And it\'s got nothing to do with the Optimus Tesla Bot!\n\nA look at how ceramic capacitor..."),
),
ChannelVideo(
VideoItem(
id: "W1Jl0rMRGSg",
title: "EEVblog 1503 - Rigol HDO4000 12bit Oscilloscope TEARDOWN",
length: Some(1798),
@ -269,14 +276,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("11 days ago"),
view_count: 36129,
view_count: Some(36129),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Teardown of the new Rigol HDO4000 12bit ultra low noise oscilloscope\n\nPSU teardown: https://www.youtube.com/watch?v=muMjiao5i0k\n\nForum: https://www.eevblog.com/forum/testgear/rigol-hdo1000-and-hdo4..."),
),
ChannelVideo(
VideoItem(
id: "YFKu_emNzpk",
title: "EEVblog 1502 - Is Home Battery Storage Financially Viable?",
length: Some(1199),
@ -302,14 +311,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 87357,
view_count: Some(87357),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Running through the numbers to see if home battery storage is viable on my home. \nAnd comparing Tesla Powerwall, Enphase IQ Battery, BYD LVS, and Greenbank battery pricing.\n\nAll my solar videos:..."),
),
ChannelVideo(
VideoItem(
id: "gremHHvqYTE",
title: "EEVblog 1501 - Rigol HDO4000 Low Noise 12bit Oscilloscope Unboxing & First Impression",
length: Some(1794),
@ -335,14 +346,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 48259,
view_count: Some(48259),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Rigol\'s new HDO4000 Series ultra low noise 12bit oscilloscope with Centaur chipset.\nUnboxing, first impression, and noise measurements.\n\nAC RMS noise measurement: https://www.youtube.com/watch?v=G8..."),
),
ChannelVideo(
VideoItem(
id: "WHO8NBfpaO0",
title: "eevBLAB 102 - Last Mile Autonomous Robot Deliveries WILL FAIL",
length: Some(742),
@ -368,14 +381,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 27509,
view_count: Some(27509),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Four reasons why autonomous pizza delivery robots will FAIL.\nAnd nope, they won\'t save the environment either.\nBut maybe I\'m wrong?\nMagna are trialing a pizza delivery robot in Manhatten.\n..."),
),
ChannelVideo(
VideoItem(
id: "W1Q8CxL95_Y",
title: "EEVblog 1500 - Automatic Transfer Switch REVERSE ENGINEERED",
length: Some(1770),
@ -401,14 +416,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 57925,
view_count: Some(57925),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Automatic AC transfer switches are pretty cool devices. A look at what they do, a practical demo, teardown, and then reverse engineering to explain how it does it with a direct one-to-one schematic..."),
),
ChannelVideo(
VideoItem(
id: "lagxSrPeoYg",
title: "EEVblog 1499 - EcoFlow Delta Pro 3.6kWh Portable Battery TEARDOWN!",
length: Some(2334),
@ -434,14 +451,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 77907,
view_count: Some(77907),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Teardown of the EcoFlow Delta Pro 3.6kWh portable/home LiFePO4 battery solar inverter/generator.\nBack in the old EEVblog garage!\n\nTeardown photos: https://www.eevblog.com/2022/09/08/eevblog-1499-ec..."),
),
ChannelVideo(
VideoItem(
id: "qTctWW9_FmE",
title: "EEVblog 1498 - TransPod Fluxjet Hyperloop $550M Boondoggle!",
length: Some(2399),
@ -467,14 +486,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 63421,
view_count: Some(63421),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("The Transpod FluxJet is Hyperloop based on the \"New physics\" of \"Veillance Flux\"!\nAnd plasma arc power transfer!\n$550M to create a reduced pressure Fluxjet link from Calgary to Edmonton in..."),
),
ChannelVideo(
VideoItem(
id: "3t9G80wk0pk",
title: "eevBLAB 101 - Why Are Tektronix Oscilloscopes So Expensive?",
length: Some(1423),
@ -500,14 +521,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 73052,
view_count: Some(73052),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Answering the question of why Tektronix and the other top tier manufactuer\'s oscilloscopes are so expensive? Why don\'t they just make a low cost scope?\nHere is a list of 16 reasons, can you..."),
),
ChannelVideo(
VideoItem(
id: "7dze5CnZnmk",
title: "EEVblog 1497 - RIP Fluke. Thanks Energizer. NOT.",
length: Some(1168),
@ -533,14 +556,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 93529,
view_count: Some(93529),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("RIP this Fluke 3000 wireless multimeter. Thanks Energizer for the alkaline battery leakage!\n\nPART 2 Repair: https://www.youtube.com/watch?v=qmcSEJehqZM\n\nEnergizer battery leakage in liquid..."),
),
ChannelVideo(
VideoItem(
id: "6XnrZpPYgBg",
title: "EEVblog 1496 - Winning Mailbag",
length: Some(3139),
@ -566,14 +591,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 41569,
view_count: Some(41569),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Meet 13yo Josh, the winner of the Jaycar $5 scope, and designer of Framework laptop boards!\nhttps://lectronz.com/products/uart-expansion-card\nHis Patreon: https://www.patreon.com/i2clabs\nMore..."),
),
ChannelVideo(
VideoItem(
id: "Psp3ltpFvws",
title: "eevBLAB 100 - Reuters Attacks Odysee - LOL",
length: Some(855),
@ -599,14 +626,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 22842,
view_count: Some(22842),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Reuters attacks Odysee for hosting conspiracy and violent content and gets OWNED, LOL.\nLet\'s actually take look to see if that\'s the case. SPOILER: It\'s not, Odysee is fantastic.\nWatch an an..."),
),
ChannelVideo(
VideoItem(
id: "taVYTYz5vLE",
title: "EEVblog 1495 - Quaze Wireless Power (AGAIN!) but for GAMING!",
length: Some(2592),
@ -632,14 +661,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 41621,
view_count: Some(41621),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Yes, wireless power is BACK! And this time they are targetting gaming rigs.\nQuaze want to power gaming rigs up to 500W with 15MHz resonant RF wireless desktop power. Let\'s take a look! How..."),
),
ChannelVideo(
VideoItem(
id: "Y6cZrieFw-k",
title: "EEVblog 1494 - FIVE Ways to Open a CHEAP SAFE!",
length: Some(1194),
@ -665,14 +696,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 77542,
view_count: Some(77542),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("FIVE different easy methods to crack into a cheap Sandleford safe found in the dumpster, WITHOUT using physical force. Including a bonus 6th method that doesn\'t work on this one.\nDon\'t buy..."),
),
ChannelVideo(
VideoItem(
id: "Kr2XyhpUdUI",
title: "EEVblog 1493 - MacGyver Project - Part 2",
length: Some(1785),
@ -698,14 +731,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 34947,
view_count: Some(34947),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Powering up the Banshee ultrasonic leak detector LED display to see how the display is multiplexed turned out to be very interesting!\nWith special guest debugger, Sagan, who invents a new industry..."),
),
ChannelVideo(
VideoItem(
id: "rxGafdgkal8",
title: "EEVblog 1492 - $5 Oscilloscope Repaired! + Oz GIVEAWAY",
length: Some(1163),
@ -731,14 +766,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 45618,
view_count: Some(45618),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("The $5 Hantek oscilloscope is repaired, and I\'m giving it away to a youngster in Australia.\n\nIf you want the scope, enter here:\nhttps://www.eevblog.com/forum/contests/giveaway-(oz-only)-hantek-osci..."),
),
ChannelVideo(
VideoItem(
id: "4yosozyeIP4",
title: "EEVblog 1491 - The MacGyver Project - Part 1",
length: Some(1706),
@ -764,14 +801,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 34868,
view_count: Some(34868),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Part 1 reverse engineering the interface on the LED display of the Banshee Ultrasonic gas leak detector to make a MacGyver type countdown timer THING (for demonetisation purposes).\nThis will..."),
),
ChannelVideo(
VideoItem(
id: "06JtC2DC_dQ",
title: "EEVblog 1490 - Insane Jaycar Dumpster Sale! 2022",
length: Some(1700),
@ -797,14 +836,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 64336,
view_count: Some(64336),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Insane Jaycar dumpster relocation sale!\n\nSupport the EEVblog on:\nPatreon: http://www.patreon.com/eevblog\nOdysee: https://odysee.com/@eevblog:7\nWeb Site: http://www.eevblog.com\nEEVblog2: http://www...."),
),
ChannelVideo(
VideoItem(
id: "piquT76w9TI",
title: "EEVblog 1489 - Mystery Teardown!",
length: Some(1466),
@ -830,14 +871,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 150958,
view_count: Some(150958),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Teardown of a bizarre looking Banshee 343 Ultrasonic Gas Leak Detector\n\nThumbs up this video and pinned comment if you want to see a countdown timer refit project!\n\nDatasheet: https://www.instrumar..."),
),
ChannelVideo(
VideoItem(
id: "pKuUKT-zU-g",
title: "EEVblog 1488 - Tilt Five Augmented Reality AR Glasses - First Reaction!",
length: Some(2152),
@ -863,14 +906,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 30903,
view_count: Some(30903),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Dave tries Jeri Ellsworth\'s Tilt Five augmented reality AR glasses for the first time!\nUnboxing, first reaction, and a bit of a first user review.\n\n00:00 - Tilt Five AR Kickstarter Glasses..."),
),
ChannelVideo(
VideoItem(
id: "_R4wQQNSO6k",
title: "EEVblog 1487 - Do Solar Micro Inverters Take Power at Night?",
length: Some(2399),
@ -896,14 +941,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 48669,
view_count: Some(48669),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("How much power do Enphase and other solar micro inverters draw at night time when switched off? It\'s actually a very interesting question involving real and apparent/reactive power, the system..."),
),
ChannelVideo(
VideoItem(
id: "ikp5BorIo_M",
title: "EEVblog 1486 - What you DIDN\'T KNOW About Film Capacitor FAILURES!",
length: Some(1792),
@ -929,14 +976,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 83505,
view_count: Some(83505),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("You might think you know how film capacitors fail and degrade in capacitance over time - self-healing due to surges, right? WRONG!\nCapacitor expert and AVX Fellow Ron Demcko confirms what\'s..."),
),
ChannelVideo(
VideoItem(
id: "7O-QckjCXNo",
title: "eevBLAB 99 - AI SPAM BOT Youtube Space/Science/Tech Channels? - WTF",
length: Some(592),
@ -962,14 +1011,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 42843,
view_count: Some(42843),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("WTF are these random mash content spam space/science/tech Youtube channels? Are they auto-generated AI bots?\nThese channels get over 1M views a day!\nhttps://www.youtube.com/channel/UC2jAc3ifBNVT03i..."),
),
ChannelVideo(
VideoItem(
id: "VutdTxF4E-0",
title: "RIP The Old Garage Lab",
length: Some(115),
@ -995,14 +1046,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 26036,
view_count: Some(26036),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("RIP The old EEVblog garage lab.\nA slightly extended tour of the old lab: https://odysee.com/@eevblog:7/2021-06-11-Old-Lab-Tour:2\nSecret feature of the EEVblog lab bench: https://www.youtube.com/wat..."),
),
ChannelVideo(
VideoItem(
id: "o7xfGuRaq94",
title: "EEVblog 1485 - PedalCell CadenceX Bike Generator LOL FAIL!",
length: Some(1026),
@ -1028,14 +1081,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 63729,
view_count: Some(63729),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("The failed PedalCell CadenceX Bike Generator from the previous mailbag video is tested, torn down, analysed, hilrariously laughed at, and dodgily repaired.\nhttps://pedalcell.com/\n\n00:00 - Failed..."),
),
ChannelVideo(
VideoItem(
id: "3WSIfHOv3fc",
title: "EEVblog 1484 - Kaba Mas X-09 High Security Electronic Lock Teardown",
length: Some(1106),
@ -1061,14 +1116,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 22920,
view_count: Some(22920),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Extended version of the Mailbag 1483 teardown of the Kaba Mas X-09 High Security Electronic Lock Teardown\n\nSupport the EEVblog on:\nPatreon: http://www.patreon.com/eevblog\nOdysee: https://odysee.com..."),
),
ChannelVideo(
VideoItem(
id: "8yXZJZCKImI",
title: "EEVblog 1483 - Holy Mailbag Bomb Batman!",
length: Some(3373),
@ -1094,14 +1151,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 66042,
view_count: Some(66042),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("Bumper Mailbag!\n\nForum: https://www.eevblog.com/forum/blog/eevblog-1483-holy-mailbag-bomb-batman/\n\nSPOILERS:\n00:00 - Contact Harald Covid Bluetooth Tracing \n04:24 - Kaba Mas X09 High Security..."),
),
ChannelVideo(
VideoItem(
id: "vJ4pW6LKJWU",
title: "EEVblog 1482 - Mains Capacitor Zener Regulator Circuit",
length: Some(1132),
@ -1127,14 +1186,17 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 52065,
view_count: Some(52065),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: Some("A follow up to the previous video on repairing the heater.\nA viewer asked how the capacitor diode rectifier gave a 24V output. The key is in the zener regulator, so this vidoe looks at how..."),
),
],
ctoken: Some("4qmFsgKhARIYVUMyRGpGRTdYZjExVVJacVdCaWdjVk9RGoQBOGdaZ0dsNTZYQXBZQ2pCRlozTkpOV054YjJ4eWNYSnBjeTA0UVZObmVVMUJSVFJJYTBsTVEwbEhjV3cxYjBkRlVHcHlYM2hTU1VGV1FVRVNKRFl6TkRZMVlqZzFMVEF3TURBdE1qTXlOaTA1WTJSbUxUTmpNamcyWkRReU1tWTNOaGdC"),
endpoint: browse,
),
)

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: Verified,
description: "NO SCRIPT, NO FEAR, ALL OPINION\nAn off-the-cuff Video Blog about Electronics Engineering, for engineers, hobbyists, enthusiasts, hackers and Makers\nHosted by Dave Jones from Sydney Australia\n\nDONATIONS:\nBitcoin: 3KqyH1U3qrMPnkLufM2oHDU7YB4zVZeFyZ\nEthereum: 0x99ccc4d2654ba40744a1f678d9868ecb15e91206\nPayPal: david@alternatezone.com\n\nPatreon: https://www.patreon.com/eevblog\n\nEEVblog2: http://www.youtube.com/EEVblog2\nEEVdiscover: https://www.youtube.com/channel/UCkGvUEt8iQLmq3aJIMjT2qQ\n\nEMAIL:\nAdvertising/Commercial: eevblog+business@gmail.com\nFan mail: eevblog+fan@gmail.com\nHate Mail: eevblog+hate@gmail.com\n\nI DON\'T DO PAID VIDEO SPONSORSHIPS, DON\'T ASK!\n\nPLEASE:\nDo NOT ask for personal advice on something, post it in the EEVblog forum.\nI read ALL email, but please don\'t be offended if I don\'t have time to reply, I get a LOT of email.\n\nMailbag\nPO Box 7949\nBaulkham Hills NSW 2153\nAUSTRALIA",
tags: [
"electronics",
@ -144,7 +145,7 @@ Channel(
content: Paginator(
count: None,
items: [
ChannelVideo(
VideoItem(
id: "gremHHvqYTE",
title: "EEVblog 1501 - Rigol HDO4000 Low Noise 12bit Oscilloscope Unboxing & First Impression",
length: Some(1794),
@ -170,14 +171,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("20 hours ago"),
view_count: 19739,
view_count: Some(19739),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "WHO8NBfpaO0",
title: "eevBLAB 102 - Last Mile Autonomous Robot Deliveries WILL FAIL",
length: Some(742),
@ -203,14 +206,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("5 days ago"),
view_count: 24194,
view_count: Some(24194),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "W1Q8CxL95_Y",
title: "EEVblog 1500 - Automatic Transfer Switch REVERSE ENGINEERED",
length: Some(1770),
@ -236,14 +241,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 days ago"),
view_count: 51443,
view_count: Some(51443),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "lagxSrPeoYg",
title: "EEVblog 1499 - EcoFlow Delta Pro 3.6kWh Portable Battery TEARDOWN!",
length: Some(2334),
@ -269,14 +276,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("13 days ago"),
view_count: 72324,
view_count: Some(72324),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "qTctWW9_FmE",
title: "EEVblog 1498 - TransPod Fluxjet Hyperloop $550M Boondoggle!",
length: Some(2399),
@ -302,14 +311,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 57348,
view_count: Some(57348),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "3t9G80wk0pk",
title: "eevBLAB 101 - Why Are Tektronix Oscilloscopes So Expensive?",
length: Some(1423),
@ -335,14 +346,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 68645,
view_count: Some(68645),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "7dze5CnZnmk",
title: "EEVblog 1497 - RIP Fluke. Thanks Energizer. NOT.",
length: Some(1168),
@ -368,14 +381,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 91388,
view_count: Some(91388),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "6XnrZpPYgBg",
title: "EEVblog 1496 - Winning Mailbag",
length: Some(3139),
@ -401,14 +416,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 39993,
view_count: Some(39993),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "Psp3ltpFvws",
title: "eevBLAB 100 - Reuters Attacks Odysee - LOL",
length: Some(855),
@ -434,14 +451,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 weeks ago"),
view_count: 22512,
view_count: Some(22512),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "taVYTYz5vLE",
title: "EEVblog 1495 - Quaze Wireless Power (AGAIN!) but for GAMING!",
length: Some(2592),
@ -467,14 +486,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 40137,
view_count: Some(40137),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "Y6cZrieFw-k",
title: "EEVblog 1494 - FIVE Ways to Open a CHEAP SAFE!",
length: Some(1194),
@ -500,14 +521,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 74510,
view_count: Some(74510),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "Kr2XyhpUdUI",
title: "EEVblog 1493 - MacGyver Project - Part 2",
length: Some(1785),
@ -533,14 +556,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 34487,
view_count: Some(34487),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "rxGafdgkal8",
title: "EEVblog 1492 - $5 Oscilloscope Repaired! + Oz GIVEAWAY",
length: Some(1163),
@ -566,14 +591,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 44928,
view_count: Some(44928),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "4yosozyeIP4",
title: "EEVblog 1491 - The MacGyver Project - Part 1",
length: Some(1706),
@ -599,14 +626,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 34324,
view_count: Some(34324),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "06JtC2DC_dQ",
title: "EEVblog 1490 - Insane Jaycar Dumpster Sale! 2022",
length: Some(1700),
@ -632,14 +661,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 63763,
view_count: Some(63763),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "piquT76w9TI",
title: "EEVblog 1489 - Mystery Teardown!",
length: Some(1466),
@ -665,14 +696,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 149186,
view_count: Some(149186),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "pKuUKT-zU-g",
title: "EEVblog 1488 - Tilt Five Augmented Reality AR Glasses - First Reaction!",
length: Some(2152),
@ -698,14 +731,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 30130,
view_count: Some(30130),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "_R4wQQNSO6k",
title: "EEVblog 1487 - Do Solar Micro Inverters Take Power at Night?",
length: Some(2399),
@ -731,14 +766,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 48037,
view_count: Some(48037),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "ikp5BorIo_M",
title: "EEVblog 1486 - What you DIDN\'T KNOW About Film Capacitor FAILURES!",
length: Some(1792),
@ -764,14 +801,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 81958,
view_count: Some(81958),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "7O-QckjCXNo",
title: "eevBLAB 99 - AI SPAM BOT Youtube Space/Science/Tech Channels? - WTF",
length: Some(592),
@ -797,14 +836,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 42635,
view_count: Some(42635),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "VutdTxF4E-0",
title: "RIP The Old Garage Lab",
length: Some(115),
@ -830,14 +871,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 25860,
view_count: Some(25860),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "o7xfGuRaq94",
title: "EEVblog 1485 - PedalCell CadenceX Bike Generator LOL FAIL!",
length: Some(1026),
@ -863,14 +906,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 63035,
view_count: Some(63035),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "3WSIfHOv3fc",
title: "EEVblog 1484 - Kaba Mas X-09 High Security Electronic Lock Teardown",
length: Some(1106),
@ -896,14 +941,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 22731,
view_count: Some(22731),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "8yXZJZCKImI",
title: "EEVblog 1483 - Holy Mailbag Bomb Batman!",
length: Some(3373),
@ -929,14 +976,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 65765,
view_count: Some(65765),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "vJ4pW6LKJWU",
title: "EEVblog 1482 - Mains Capacitor Zener Regulator Circuit",
length: Some(1132),
@ -962,14 +1011,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 51555,
view_count: Some(51555),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "myqiqUE00fo",
title: "EEVblog 1481 - Dodgy Dangerous Heater REPAIR",
length: Some(1622),
@ -995,14 +1046,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 46638,
view_count: Some(46638),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "xIokNnjuam8",
title: "EEVblog 1480 - Lightyear Zero Solar Powered Electric Car",
length: Some(1196),
@ -1028,14 +1081,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 62921,
view_count: Some(62921),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "S3R4r2xvVYQ",
title: "EEVblog 1479 - Is Your Calculator WRONG?",
length: Some(1066),
@ -1061,14 +1116,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 66895,
view_count: Some(66895),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "RlwcdUnRw6w",
title: "EEVblog 1478 - Waveform Update Rate Shootout - Tek 2 Series vs Others",
length: Some(1348),
@ -1094,14 +1151,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 25894,
view_count: Some(25894),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "R2fw2g6WFbg",
title: "EEVblog 1477 - TEARDOWN! - NEW Tektronix 2 Series Oscilloscope",
length: Some(2718),
@ -1127,14 +1186,17 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 80173,
view_count: Some(80173),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("4qmFsgKrARIYVUMyRGpGRTdYZjExVVJacVdCaWdjVk9RGmBFZ1oyYVdSbGIzTVlBeUFBTUFFNEFlb0RNRVZuYjBsMVMzWlpPVXREWWw5TVRraExSRWwzUVZSblpWRm5kMGx3ZFVOMGJWRlpVVjlOUjA1d2QwcEpRVlpCUVElM0QlM0SaAixicm93c2UtZmVlZFVDMkRqRkU3WGYxMVVSWnFXQmlnY1ZPUXZpZGVvczEwMg%3D%3D"),
endpoint: browse,
),
)

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: None,
description: "",
tags: [],
vanity_url: None,
@ -33,5 +34,6 @@ Channel(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
)

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: Verified,
description: "Welcome to The Good Life by Sensual Musique.\nThe second official channel of Sensual Musique. You can find a lot of music, live streams and some other things on this channel. Stay tuned :)\n\nSubmit your music here: submit.sensualmusiquenetwork@gmail.com",
tags: [
"live radio",
@ -128,7 +129,7 @@ Channel(
content: Paginator(
count: Some(21),
items: [
ChannelVideo(
VideoItem(
id: "csP93FGy0bs",
title: "Chill Out Music Mix • 24/7 Live Radio | Relaxing Deep House, Chillout Lounge, Vocal & Instrumental",
length: None,
@ -154,14 +155,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: None,
view_count: 94,
is_live: true,
view_count: Some(94),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "19hKXI1ENrY",
title: "Deep House Radio | Relaxing & Chill House, Best Summer Mix 2022, Gym & Workout Music",
length: None,
@ -187,14 +190,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: None,
view_count: 381,
is_live: true,
view_count: Some(381),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "CqMUC5eXX7c",
title: "Back To School / Work 📚 Deep Focus Chillout Mix | The Good Life Radio #4",
length: Some(4667),
@ -220,14 +225,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 241528,
view_count: Some(241528),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "A77SYlXKQEM",
title: "Chillout Lounge 🏖\u{fe0f} Calm & Relaxing Background Music | The Good Life Radio #3",
length: Some(1861),
@ -253,14 +260,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 118351,
view_count: Some(118351),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "72vkRHQfjbk",
title: "Summer Lovers 💖 A Beautiful & Relaxing Chillout Deep House Mix | The Good Life Radio #2",
length: Some(1832),
@ -286,14 +295,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 157971,
view_count: Some(157971),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "AMWMDhibROw",
title: "Relaxing & Chill House 🌴 Summer \'21 Chill-Out Mix | The Good Life Radio #1",
length: Some(1949),
@ -319,14 +330,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 82309,
view_count: Some(82309),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "9UMxZofMNbA",
title: "Chillout Lounge - Calm & Relaxing Background Music | Study, Work, Sleep, Meditation, Chill",
length: None,
@ -352,14 +365,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: None,
view_count: 2043,
is_live: true,
view_count: Some(2043),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "a2sEYVwBvX4",
title: "Paratone - Heaven Is A Place On Earth (feat. kaii)",
length: Some(161),
@ -385,14 +400,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 186475,
view_count: Some(186475),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "JAY-prtJnGY",
title: "Joseph Feinstein - Where I Belong",
length: Some(126),
@ -418,14 +435,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 66425,
view_count: Some(66425),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "DySa8OrQDi4",
title: "LA Vision & Gigi D\'Agostino - Hollywood",
length: Some(200),
@ -451,14 +470,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 1520020,
view_count: Some(1520020),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "NqzXULaB8MA",
title: "LO - Home",
length: Some(163),
@ -484,14 +505,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 37549,
view_count: Some(37549),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "UGzy6uhZkmw",
title: "Luca - Sunset",
length: Some(153),
@ -517,14 +540,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 33002,
view_count: Some(33002),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "iuvapHKpW8A",
title: "nourii - Better Off (feat. BCS)",
length: Some(126),
@ -550,14 +575,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 42036,
view_count: Some(42036),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "n_1Nwht-Gh4",
title: "Deep House Covers & Remixes of Popular Songs 2020 🌴 Deep House, G-House, Chill-Out Music Playlist",
length: Some(2940),
@ -583,14 +610,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 322935,
view_count: Some(322935),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "6TptI5BtP5U",
title: "The Good Life Radio Mix #2 | Summer Memories ☀\u{fe0f} (Chill Music Playlist 2020)",
length: Some(3448),
@ -616,14 +645,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 91980,
view_count: Some(91980),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "36YnV9STBqc",
title: "The Good Life Radio\u{a0}•\u{a0}24/7 Live Radio | Best Relax House, Chillout, Study, Running, Gym, Happy Music",
length: None,
@ -649,14 +680,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: None,
view_count: 4030,
is_live: true,
view_count: Some(4030),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "7x6ii2TcsPE",
title: "The Good Life Radio Mix #1 | Relaxing & Chill House Music Playlist 2020",
length: Some(2726),
@ -682,14 +715,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 288098,
view_count: Some(288098),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "mxV5MBZYYDE",
title: "Christmas Music with Vocals 🎅 Best Relaxing Christmas Songs 2020",
length: Some(5863),
@ -715,14 +750,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 50818,
view_count: Some(50818),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "hh2AOoPoAIo",
title: "The Good Life Radio Mix 2019 🎅 Winter & Christmas Relax House Playlist [Best of Part 1]",
length: Some(2530),
@ -748,14 +785,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 98431,
view_count: Some(98431),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "aFlvhtWsJ0g",
title: "Chillout Playlist | Relaxing Summer Music Mix 2019 [Deep & Tropical House]",
length: Some(2483),
@ -781,14 +820,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 572456,
view_count: Some(572456),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "cD-d7u6fnEI",
title: "Chill House Playlist | Relaxing Summer Music 2019",
length: Some(3165),
@ -814,14 +855,17 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 3114909,
view_count: Some(3114909),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: None,
endpoint: browse,
),
)

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: None,
description: "",
tags: [],
vanity_url: None,
@ -116,5 +117,6 @@ Channel(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
)

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: Verified,
description: "Hi, Im Tina, aka Doobydobap!\n\nFood is the medium I use to tell stories and connect with people who share the same passion as I do. Whether its because youre hungry at midnight or trying to learn how to cook, I hope you enjoy watching my content and recipes. Don\'t yuck my yum!\n\nwww.doobydobap.com\n",
tags: [],
vanity_url: Some("https://www.youtube.com/c/Doobydobap"),
@ -115,7 +116,7 @@ Channel(
content: Paginator(
count: None,
items: [
ChannelVideo(
VideoItem(
id: "JBUZE0mIlg8",
title: "small but sure joy",
length: None,
@ -126,14 +127,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 day ago"),
view_count: 443549,
view_count: Some(443549),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "SRrvxFc2b2c",
title: "i don\'t believe in long distance relationships",
length: None,
@ -144,14 +147,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 days ago"),
view_count: 1154962,
view_count: Some(1154962),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "l9TiwunjzgA",
title: "long distance",
length: Some(1043),
@ -177,14 +182,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 days ago"),
view_count: 477460,
view_count: Some(477460),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "cNx0ql9gnf4",
title: "come over :)",
length: None,
@ -195,14 +202,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 days ago"),
view_count: 1388173,
view_count: Some(1388173),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "fGQUWI4o__A",
title: "Baskin Robbins in South Korea",
length: None,
@ -213,14 +222,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 days ago"),
view_count: 1738301,
view_count: Some(1738301),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "Q73VTjdqVA8",
title: "dry hot pot",
length: None,
@ -231,14 +242,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("9 days ago"),
view_count: 1316594,
view_count: Some(1316594),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "pRVSdUxdsVw",
title: "Repairing...",
length: Some(965),
@ -264,14 +277,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("10 days ago"),
view_count: 478703,
view_count: Some(478703),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "gTG2WDbiYGo",
title: "time machine",
length: None,
@ -282,14 +297,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("11 days ago"),
view_count: 1412213,
view_count: Some(1412213),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "y5JK5YFp92g",
title: "tiramissu",
length: None,
@ -300,14 +317,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("13 days ago"),
view_count: 1513305,
view_count: Some(1513305),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "pvSWHm4wlxY",
title: "having kids",
length: None,
@ -318,14 +337,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 8936223,
view_count: Some(8936223),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "2FJVhdOO0F0",
title: "a health scare",
length: Some(1238),
@ -351,14 +372,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 987083,
view_count: Some(987083),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "CqFGACRrWJE",
title: "just do it",
length: None,
@ -369,14 +392,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 2769717,
view_count: Some(2769717),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "CutR_1SDDzY",
title: "feels good to be back",
length: Some(1159),
@ -402,14 +427,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 497660,
view_count: Some(497660),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "DdGr6t2NqKc",
title: "coming soon",
length: None,
@ -420,14 +447,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 572107,
view_count: Some(572107),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "jKS44NMWuXw",
title: "adult money",
length: None,
@ -438,14 +467,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 1707132,
view_count: Some(1707132),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "kx1YtJM_vbI",
title: "a fig\'s journey",
length: None,
@ -456,14 +487,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 933094,
view_count: Some(933094),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "Sdbzs-1WWH0",
title: "How to.. Mozzarella 🧀",
length: None,
@ -474,14 +507,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 5985184,
view_count: Some(5985184),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "9qBHyJIDous",
title: "how to drink like a real korean",
length: None,
@ -492,14 +527,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 14741387,
view_count: Some(14741387),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "mBeFDb4gp8s",
title: "mr. krabs soup",
length: None,
@ -510,14 +547,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 2511322,
view_count: Some(2511322),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "b38r1UYqoBQ",
title: "in five years",
length: None,
@ -528,14 +567,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 2364408,
view_count: Some(2364408),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "KUz7oArksR4",
title: "running away",
length: Some(1023),
@ -561,14 +602,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 706059,
view_count: Some(706059),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "RdFk4WaifEo",
title: "a weeknight dinner",
length: None,
@ -579,14 +622,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 1947627,
view_count: Some(1947627),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "GuyGyzZcumI",
title: "McDonald\'s Michelin Burger",
length: None,
@ -597,14 +642,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 4763839,
view_count: Some(4763839),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "07Zipsb3-qU",
title: "cwispy potato pancake",
length: None,
@ -615,14 +662,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 1915695,
view_count: Some(1915695),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "3kaePnU6Clo",
title: "authenticity is overrated",
length: None,
@ -633,14 +682,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 7268944,
view_count: Some(7268944),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "rt4rXMftnpg",
title: "you can kimchi anything (T&C applies)",
length: None,
@ -651,14 +702,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 2539103,
view_count: Some(2539103),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "DTyLUvbf128",
title: "egg, soy, and perfect pot rice",
length: None,
@ -669,14 +722,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 5545680,
view_count: Some(5545680),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "DzjLBgIe_aI",
title: "love language",
length: None,
@ -687,14 +742,16 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 2202314,
view_count: Some(2202314),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "sPb2gyN-hnE",
title: "worth fighting for",
length: Some(1232),
@ -720,14 +777,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 613416,
view_count: Some(613416),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "9JboRKeJ2m4",
title: "Rating Italian McDonald\'s",
length: None,
@ -738,14 +797,17 @@ Channel(
height: 720,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 6443699,
view_count: Some(6443699),
is_live: false,
is_short: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("4qmFsgKrARIYVUNoOGdIZHR6TzJ0WGQ1OTNfYmpFcldnGmBFZ1oyYVdSbGIzTVlBeUFBTUFFNEFlb0RNRVZuYzBrM2NsTnVkazF4U1hWemRqQkJVMmQ1VFVGRk5FaHJTVXhEVUhac2NscHJSMFZKWVhWd016RkpRVlpCUVElM0QlM0SaAixicm93c2UtZmVlZFVDaDhnSGR0ek8ydFhkNTkzX2JqRXJXZ3ZpZGVvczEwMg%3D%3D"),
endpoint: browse,
),
)

View file

@ -23,6 +23,7 @@ Channel(
height: 176,
),
],
verification: Verified,
description: "BRAND NEW SECOND CHANNEL: https://youtube.com/channel/UCcsQYra-bISsFxNqnd6Javw\n\nJoin my Discord: https://discord.gg/2YcarWsc8S\n",
tags: [
"politics",
@ -132,7 +133,7 @@ Channel(
content: Paginator(
count: None,
items: [
ChannelVideo(
VideoItem(
id: "B-KjpyR4n5Q",
title: "The Online Manosphere",
length: None,
@ -158,14 +159,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: Some("2022-09-27T18:00:00+02:00"),
publish_date_txt: None,
view_count: 237,
view_count: Some(237),
is_live: false,
is_short: false,
is_upcoming: true,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "umDsCyZ67J0",
title: "Ukraine - The Beginning of the End",
length: Some(614),
@ -191,14 +194,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("13 days ago"),
view_count: 742284,
view_count: Some(742284),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "dNgKGL8lQck",
title: "Honest Russian Military Recruitment Video",
length: Some(62),
@ -224,14 +229,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 420368,
view_count: Some(420368),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "UVWciFJeFNA",
title: "Self-Driving Cars Will Only Make Traffic Worse",
length: Some(458),
@ -257,14 +264,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 528718,
view_count: Some(528718),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "vyWaax07_ks",
title: "NEOM Is The Parody Of The Future",
length: Some(636),
@ -290,14 +299,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 897237,
view_count: Some(897237),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "onQ0ICkLEJw",
title: "I Got An Email From \"The Dubai Sheikh\'s Personal Friend\"",
length: Some(211),
@ -323,14 +334,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 526638,
view_count: Some(526638),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "yDEL1pTYOhs",
title: "The \"Meritocracy\" Isn\'t Real",
length: Some(385),
@ -356,14 +369,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 368801,
view_count: Some(368801),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "EnVvlhhqWtw",
title: "City Review - Prague: Beautiful and Disappointing",
length: Some(834),
@ -389,14 +404,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 286737,
view_count: Some(286737),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "Oxz4oY0T85Y",
title: "European International Rail SUCKS, Here\'s Why",
length: Some(810),
@ -422,14 +439,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 664499,
view_count: Some(664499),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "lxUEuOkblws",
title: "Why the Straddling Bus Failed",
length: Some(614),
@ -455,14 +474,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 592227,
view_count: Some(592227),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "UG8jiKOtedk",
title: "How Canadian Ukrainian Volunteer Got Exposed",
length: Some(538),
@ -488,14 +509,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 396946,
view_count: Some(396946),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "bQld7iJJSyk",
title: "Why Roads ALWAYS Fill Up, No Matter How Much We Widen Them",
length: Some(159),
@ -521,14 +544,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 778430,
view_count: Some(778430),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "WUK0K5mdQ_s",
title: "Egypt\'s New Capital is an Ozymandian Nightmare",
length: Some(870),
@ -554,14 +579,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 2118499,
view_count: Some(2118499),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "LB-vsT1Sl68",
title: "Why Car-Centric Cities are a GREAT Idea",
length: Some(369),
@ -587,14 +614,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 525824,
view_count: Some(525824),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "p8NiM_p8n5A",
title: "HE FIXED TRAFFIC",
length: Some(157),
@ -620,14 +649,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 1097056,
view_count: Some(1097056),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "U9YdnzOf4NQ",
title: "Why a Mars Colony is a Stupid and Dangerous Idea",
length: Some(1000),
@ -653,14 +684,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 1532114,
view_count: Some(1532114),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "CH55WpJxF1s",
title: "What #Elongate Is Really About",
length: Some(122),
@ -686,14 +719,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 511601,
view_count: Some(511601),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "PPcsZwUv350",
title: "Vladimir Putin\'s Three Choices",
length: Some(505),
@ -719,14 +754,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 662099,
view_count: Some(662099),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "B78-FgNqdc8",
title: "Was I WRONG About Electric Buses?",
length: Some(1536),
@ -752,14 +789,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 549826,
view_count: Some(549826),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "JCXLwOMSDxk",
title: "If We Treated Afghanistan Like Ukraine",
length: Some(92),
@ -785,14 +824,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 538197,
view_count: Some(538197),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "IpIWswLYAbA",
title: "Who\'s Winning the War for Ukraine?",
length: Some(646),
@ -818,14 +859,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("5 months ago"),
view_count: 536648,
view_count: Some(536648),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "NIItoD1Ebh0",
title: "Old Habits Die Hard",
length: Some(107),
@ -851,14 +894,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("5 months ago"),
view_count: 724630,
view_count: Some(724630),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "pENUV9DLa2g",
title: "Anarcho-Capitalism In Practice III - The Final Attempt",
length: Some(600),
@ -884,14 +929,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("5 months ago"),
view_count: 426960,
view_count: Some(426960),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "gFGQI8P9BMg",
title: "How The Gravel Institute Lies To You About Ukraine",
length: Some(2472),
@ -917,14 +964,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 735941,
view_count: Some(735941),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "AVLevneWvaE",
title: "Why Russia Can\'t Achieve Air Supremacy In Ukraine",
length: Some(188),
@ -950,14 +999,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 502205,
view_count: Some(502205),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "MfRcY90OccY",
title: "Can Ukraine Actually WIN This?",
length: Some(606),
@ -983,14 +1034,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 718668,
view_count: Some(718668),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "dQXwreYzJ40",
title: "Here\'s What Will Happen To Ukraine [Update: yep, called it]",
length: Some(397),
@ -1016,14 +1069,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 775830,
view_count: Some(775830),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "-OO3RiNMDB8",
title: "Assessing The Russian Invasion Threat",
length: Some(655),
@ -1049,14 +1104,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 480357,
view_count: Some(480357),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "obMTYs30E9A",
title: "Ukraine - The Country That Defied Vladimir Putin",
length: Some(2498),
@ -1082,14 +1139,16 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 460878,
view_count: Some(460878),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
ChannelVideo(
VideoItem(
id: "4-2bR1iFlhk",
title: "\"Wait, Russia isn\'t in NATO?!\" Insane Debate on Ukraine, US Politics, and more!",
length: Some(12151),
@ -1115,14 +1174,17 @@ Channel(
height: 188,
),
],
channel: None,
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 228151,
view_count: Some(228151),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("4qmFsgKnARIYVUNjdmZIYS1HSFNPSEZBalUwLUllNTdBGlxFZ1oyYVdSbGIzTVlBeUFBTUFFNEFlb0RNa1ZuYzBsdFlYbFhlRkJZYnpWMlltcEJVMmQ1VFVGRk5FaHJTVTFEVFdGVWVrcHJSMFZPUzJzMmNqQkNVMEZHVVVGQpoCLGJyb3dzZS1mZWVkVUNjdmZIYS1HSFNPSEZBalUwLUllNTdBdmlkZW9zMTAy"),
endpoint: browse,
),
)

View file

@ -1,11 +1,11 @@
---
source: src/client/channel.rs
source: src/client/pagination.rs
expression: map_res.c
---
Paginator(
count: None,
items: [
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHutdg1kZkG7aAYhjoJnk2fc",
name: "Nixie Tube Display Project",
thumbnail: [
@ -15,9 +15,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(9),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHujYmL_-5CBUg-za2osSUVI",
name: "Mystery Teardown",
thumbnail: [
@ -27,9 +28,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(16),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHuGQmy-eJgqB28b2AWKteuG",
name: "EEVsmoke",
thumbnail: [
@ -39,9 +41,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(2),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHuSab0CmpulB2Wv8Kz0985m",
name: "EEVcomments",
thumbnail: [
@ -51,9 +54,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvtQ5FxEivbCGxp4t3W8zKE",
name: "Spectrum Analyser",
thumbnail: [
@ -63,9 +67,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(11),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHuJUxiTbVKHzWjvIVf1NVOl",
name: "Space",
thumbnail: [
@ -75,9 +80,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(5),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtTXTVCXVDIRKV442ynD7Pz",
name: "Lunar Rover",
thumbnail: [
@ -87,9 +93,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHsma5qL7piUiM5N4IOyuQyx",
name: "Wayback Wednesday",
thumbnail: [
@ -99,9 +106,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvLb_HJBKqbgZ9IvEX-pVOF",
name: "Magazines",
thumbnail: [
@ -111,9 +119,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(4),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHugE85Y_LckT4EhrKwo7WQe",
name: "Embedded Computing",
thumbnail: [
@ -123,9 +132,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(4),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHu3GsTHwHoAXlWVcL3c3dA0",
name: "High Speed Camera",
thumbnail: [
@ -135,9 +145,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(2),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvTyDxI-_RDK8UlPbJ5FNf9",
name: "Announcements & Misc",
thumbnail: [
@ -147,9 +158,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(28),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtT17_AeYMe-EOS_GXCBQQ1",
name: "Interviews",
thumbnail: [
@ -159,9 +171,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(9),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHsCTtj-T_vkpTTbBXW4sB51",
name: "Oscilloscope Tutorials",
thumbnail: [
@ -171,9 +184,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(38),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHsKCtJJ_rlRP5qE7lN-1EMX",
name: "Anti-Static ESD",
thumbnail: [
@ -183,9 +197,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(7),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvFf9a2swL8QVMwji0wT3ha",
name: "Unboxing",
thumbnail: [
@ -195,9 +210,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(2),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtn9n6n-uB8VNCTrERwYxLZ",
name: "Power Supplies",
thumbnail: [
@ -207,9 +223,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(43),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHuo-6paPTh3ji7AEMpnSna6",
name: "CNC Milling Machine",
thumbnail: [
@ -219,9 +236,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(1),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvpVeLXSGlS7EBlY3zKfIXh",
name: "Capacitors",
thumbnail: [
@ -231,9 +249,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(15),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHsNGit9YgkuxsFtFNJxwgot",
name: "PCB Assembly",
thumbnail: [
@ -243,9 +262,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(5),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvsggk5TwGdR2BZcoKRkQ2I",
name: "3D Printing",
thumbnail: [
@ -255,9 +275,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(6),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtH_DR5hAIGQ-Ty6f9TZWNV",
name: "Video Editing / PC Builds",
thumbnail: [
@ -267,9 +288,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(3),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvPZ1-dDC449w_r2M0R4jtc",
name: "Solar Power Systems",
thumbnail: [
@ -279,9 +301,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(19),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHtolTr61FnHtvZb6tRPrs8m",
name: "EEVblab",
thumbnail: [
@ -291,9 +314,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(101),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHsc8y1buFPJZaD1kKzIxpWL",
name: "Repairs",
thumbnail: [
@ -303,9 +327,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(78),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvBpmbLABRmSKv2b0C4LWV_",
name: "Debunking",
thumbnail: [
@ -315,9 +340,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(73),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHs_8iObryqVCeqLIo5KTFQ-",
name: "Lab Bench Builds + ESD Mats",
thumbnail: [
@ -327,9 +353,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(9),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvatF_8oJ2qpKxi_wWw6YN4",
name: "Reverse Engineering",
thumbnail: [
@ -339,9 +366,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(10),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvwQR69zYRyxSkujQs2SgLl",
name: "Scams",
thumbnail: [
@ -351,9 +379,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(5),
),
ChannelPlaylist(
PlaylistItem(
id: "PLvOlSehNtuHvRvEU3VebO2JHa1I_iIAQD",
name: "Hacking / Experiments",
thumbnail: [
@ -363,8 +392,10 @@ Paginator(
height: 270,
),
],
channel: None,
video_count: Some(63),
),
],
ctoken: Some("4qmFsgLCARIYVUMyRGpGRTdYZjExVVJacVdCaWdjVk9RGnRFZ2x3YkdGNWJHbHpkSE1ZQXlBQk1BRTRBZW9EUEVOblRrUlJhbEZUU2tKSmFWVkZlREpVTW5oVVdsZG9UMlJJVmtsa2JFb3lVbFpWZWxadFZtbFVla3BMVTBkRmVGTldPWEJUVlVaU1VrTm5PQSUzRCUzRJoCL2Jyb3dzZS1mZWVkVUMyRGpGRTdYZjExVVJacVdCaWdjVk9RcGxheWxpc3RzMTA0"),
endpoint: browse,
)

View file

@ -1,11 +1,11 @@
---
source: src/client/video_details.rs
source: src/client/pagination.rs
expression: map_res.c
---
Paginator(
count: None,
items: [
RecommendedVideo(
Video(VideoItem(
id: "WPdWvnAAurg",
title: "aespa 에스파 \'Savage\' MV",
length: Some(259),
@ -21,7 +21,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -31,16 +31,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 months ago"),
view_count: 216222873,
view_count: Some(216222873),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "Y8JFxS1HlDo",
title: "IVE 아이브 \'LOVE DIVE\' MV",
length: Some(179),
@ -56,7 +58,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCYDmx2Sfpnaxg488yBpZIGg",
name: "starshipTV",
avatar: [
@ -66,16 +68,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 months ago"),
view_count: 155106313,
view_count: Some(155106313),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "NoYKBAajoyo",
title: "EVERGLOW (에버글로우) - DUN DUN MV",
length: Some(209),
@ -91,7 +95,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC_pwIXKXNm5KGhdEVzmY60A",
name: "Stone Music Entertainment",
avatar: [
@ -101,16 +105,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 265238677,
view_count: Some(265238677),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "yQUU29NwNF4",
title: "aespa(에스파) - Black Mamba @인기가요 inkigayo 20201122",
length: Some(213),
@ -126,7 +132,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCS_hnpJLQTvBkqALgapi_4g",
name: "스브스케이팝 X INKIGAYO",
avatar: [
@ -136,16 +142,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 9989591,
view_count: Some(9989591),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "NU611fxGyPU",
title: "aespa 에스파 \'Black Mamba\' Dance Practice",
length: Some(175),
@ -161,7 +169,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa",
avatar: [
@ -171,16 +179,18 @@ Paginator(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 34588526,
view_count: Some(34588526),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "EaswWiwMVs8",
title: "Stray Kids \"소리꾼(Thunderous)\" M/V",
length: Some(199),
@ -196,7 +206,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -206,16 +216,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 242737870,
view_count: Some(242737870),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "Ujb-gvqsoi0",
title: "Red Velvet - IRENE & SEULGI \'Monster\' MV",
length: Some(182),
@ -231,7 +243,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -241,16 +253,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 126677200,
view_count: Some(126677200),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "gQlMMD8auMs",
title: "BLACKPINK - Pink Venom M/V",
length: Some(194),
@ -266,7 +280,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -276,16 +290,18 @@ Paginator(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 335903776,
view_count: Some(335903776),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "BL-aIpCLWnU",
title: "Black Mamba",
length: Some(175),
@ -301,7 +317,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa",
avatar: [
@ -311,16 +327,18 @@ Paginator(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 86125645,
view_count: Some(86125645),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "Jh4QFaPmdss",
title: "(G)I-DLE - \'TOMBOY\' Official Music Video",
length: Some(198),
@ -336,7 +354,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCritGVo7pLJLUS8wEu32vow",
name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)",
avatar: [
@ -346,16 +364,18 @@ Paginator(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 170016610,
view_count: Some(170016610),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "Fc-fa6cAe2c",
title: "KAI 카이 \'음 (Mmmh)\' MV",
length: Some(207),
@ -371,7 +391,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -381,16 +401,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 123861096,
view_count: Some(123861096),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "dYRITmpFbJ4",
title: "aespa 에스파 \'Girls\' MV",
length: Some(269),
@ -406,7 +428,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -416,16 +438,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 101968219,
view_count: Some(101968219),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "mH0_XpSHkZo",
title: "TWICE \"MORE & MORE\" M/V",
length: Some(241),
@ -441,7 +465,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -451,16 +475,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 322510403,
view_count: Some(322510403),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "uR8Mrt1IpXg",
title: "Red Velvet 레드벨벳 \'Psycho\' MV",
length: Some(216),
@ -476,7 +502,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -486,16 +512,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 345491789,
view_count: Some(345491789),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "f5_wn8mexmM",
title: "TWICE \"The Feels\" M/V",
length: Some(232),
@ -511,7 +539,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -521,16 +549,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 months ago"),
view_count: 314744776,
view_count: Some(314744776),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "Ky5RT5oGg0w",
title: "aespa 에스파 \'Black Mamba\' The Debut Stage",
length: Some(287),
@ -546,7 +576,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa",
avatar: [
@ -556,16 +586,18 @@ Paginator(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 18830758,
view_count: Some(18830758),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "gU2HqP4NxUs",
title: "BLACKPINK - Pretty Savage 1011 SBS Inkigayo",
length: Some(208),
@ -581,7 +613,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -591,16 +623,18 @@ Paginator(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 282957370,
view_count: Some(282957370),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "KhTeiaCezwM",
title: "[MV] MAMAMOO (마마무) - HIP",
length: Some(211),
@ -616,7 +650,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCuhAUMLzJxlP1W7mEk0_6lA",
name: "MAMAMOO",
avatar: [
@ -626,16 +660,18 @@ Paginator(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 355203298,
view_count: Some(355203298),
is_live: false,
is_short: false,
),
RecommendedVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "uxmP4b2a0uY",
title: "EXO 엑소 \'Obsession\' MV",
length: Some(220),
@ -651,7 +687,7 @@ Paginator(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -661,15 +697,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 157400947,
view_count: Some(157400947),
is_live: false,
is_short: false,
),
is_upcoming: false,
short_description: None,
)),
],
ctoken: Some("CCgSExILWmVlcnJudUxpNUXAAQHIAQEYACrLDDJzNkw2d3l4Q1FxdUNRb0Q4ajRBQ2czQ1Bnb0l4LUM1djltdnBwZ3lDZ1B5UGdBS0RjSS1DZ2pxM0xYRXpkNk00VUVLQV9JLUFBb093ajRMQ1Bqc19JLUVsWTI5MWdFS0FfSS1BQW93MGo0dENpdFNSRU5NUVVzMWRYbGZhekkzZFhVdFJYUlJYMkkxVlRKeU1qWkVUa1JhVDIxT2NVZGtZMk5WU1VkUkNnUHlQZ0FLRHNJLUN3amZ2czJMbjRUcG5iUUJDZ1B5UGdBS0V0SS1Ed29OVWtSYVpXVnljbTUxVEdrMVJRb0Q4ajRBQ2c3Q1Bnc0kzYmJTdThMRy1wS1VBUW9EOGo0QUNnN0NQZ3NJX2JYd2lmQzJ0WlczQVFvRDhqNEFDZzdDUGdzSXpZckE3b0RHbzlMUUFRb0Q4ajRBQ2czQ1Bnb0l0N212dk9fUjVJUnZDZ1B5UGdBS0RjSS1DZ2lBcDdMWDBlYWxyaW9LQV9JLUFBb053ajRLQ0luanlmalZ0dUwxWHdvRDhqNEFDZzNDUGdvSXBKZmozYVR5X2MwZkNnUHlQZ0FLRGNJLUNnamJtNW1MbGRLQTV3Z0tBX0ktQUFvT3dqNExDTFRhOF9UNjE3U3UyQUVLQV9JLUFBb053ajRLQ05xMHBhdXZzS1BDZEFvRDhqNEFDZzdDUGdzSTVQR3E5WTIybWNXZ0FRb0Q4ajRBQ2c3Q1Bnc0lnNkdPN3JidzJjR0tBUW9EOGo0QUNnN0NQZ3NJenEtbWxQUy01SnJoQVFvRDhqNEFDZzdDUGdzSXZNbnBqSUtUeXBYX0FRb0Q4ajRBQ2czQ1Bnb0l1UFdDZ09mWDFmdFlDZ1B5UGdBS0g5SS1IQW9hVWtSRlRWUnVTbmxSZDJsamFHMW5lbm96VGxKSlVIVmxWMUVLQV9JLUFBb053ajRLQ0xxb251clN1SkhoWXdvRDhqNEFDZzNDUGdvSXFzYU90Y0RBZ3NNMkNnUHlQZ0FLRHNJLUN3amU2TUNidlp2Rmdza0JDZ1B5UGdBS0RjSS1DZ2oxa1p2aTM3cXRwelVLQV9JLUFBb053ajRLQ00tdHNlQ2lpOHpWRVFvRDhqNEFDZzNDUGdvSXJjU3kxYV9RdjV0U0NnUHlQZ0FLRHNJLUN3akw4ZXI0ZzRiVGhJRUJDZ1B5UGdBS0RjSS1DZ2oxdEsyRXFjVG0zd1FLQV9JLUFBb053ajRLQ012dG1aX2Fnb1NQSmdvRDhqNEFDZzNDUGdvSTVfYUJ1THJ0NS1jVkNnUHlQZ0FLRGNJLUNnaWUyWlhTNW9tU3duVUtBX0ktQUFvT3dqNExDSnFqbnFUcDY4LS1tQUVLQV9JLUFBb093ajRMQ1BqS291cnRsY09QdVFFS0FfSS1BQW9Od2o0S0NPT00tOHo4a196UGZ3b0Q4ajRBQ2czQ1Bnb0l6SWFhMFBtcGxKY3JDZ1B5UGdBS0RzSS1Dd2pMaXJmd2pfWGhwb0VCQ2dQeVBnQUtEY0ktQ2dpRG52dUVtdEczaWlvS0FfSS1BQW9Pd2o0TENPYWw2LXliX09PTXV3RVNLQUFDQkFZSUNnd09FQklVRmhnYUhCNGdJaVFtS0Nvc0xqQXlORFk0T2p3LVFFSkVSa2hLVEU0YUJBZ0FFQUVhQkFnQ0VBTWFCQWdFRUFVYUJBZ0dFQWNhQkFnSUVBa2FCQWdLRUFzYUJBZ01FQTBhQkFnT0VBOGFCQWdRRUJFYUJBZ1NFQk1hQkFnVUVCVWFCQWdXRUJjYUJBZ1lFQmthQkFnYUVCc2FCQWdjRUIwYUJBZ2VFQjhhQkFnZ0VDRWFCQWdpRUNNYUJBZ2tFQ1VhQkFnbUVDY2FCQWdvRUNrYUJBZ3FFQ3NhQkFnc0VDMGFCQWd1RUM4YUJBZ3dFREVhQkFneUVETWFCQWcwRURVYUJBZzJFRGNhQkFnNEVEa2FCQWc2RURzYUJBZzhFRDBhQkFnLUVEOGFCQWhBRUVFYUJBaENFRU1hQkFoRUVFVWFCQWhHRUVjYUJBaElFRWthQkFoS0VFc2FCQWhNRUUwYUJBaE9FRThxS0FBQ0JBWUlDZ3dPRUJJVUZoZ2FIQjRnSWlRbUtDb3NMakF5TkRZNE9qdy1RRUpFUmtoS1RFNGoPd2F0Y2gtbmV4dC1mZWVkcgA%3D"),
endpoint: browse,
)

View file

@ -1,11 +1,11 @@
---
source: src/client/search.rs
source: src/client/pagination.rs
expression: map_res.c
---
Paginator(
count: Some(7250),
items: [
Video(SearchVideo(
Video(VideoItem(
id: "N5AKQflK1TU",
title: "When you impulse buy...",
length: Some(60),
@ -16,7 +16,7 @@ Paginator(
height: 720,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -26,17 +26,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 day ago"),
view_count: 859366,
view_count: Some(859366),
is_live: false,
is_short: true,
short_description: "shorts #jam https://doobydobap.com/recipe/hongsi_jam Instagram @doobydobap Join my discord!",
is_upcoming: false,
short_description: Some("shorts #jam https://doobydobap.com/recipe/hongsi_jam Instagram @doobydobap Join my discord!"),
)),
Video(SearchVideo(
Video(VideoItem(
id: "OzIFALQ_YtA",
title: "taste testing gam!",
length: Some(60),
@ -47,7 +48,7 @@ Paginator(
height: 720,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -57,17 +58,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 days ago"),
view_count: 1000402,
view_count: Some(1000402),
is_live: false,
is_short: true,
short_description: "shorts #fruit #mukbang Instagram @doobydobap Join my discord! https://discord.gg/doobyverse www.doobydobap.com for\u{a0}...",
is_upcoming: false,
short_description: Some("shorts #fruit #mukbang Instagram @doobydobap Join my discord! https://discord.gg/doobyverse www.doobydobap.com for\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "zYHB38UlzE0",
title: "Q&A l relationships, burnout, privilege, college advice, living alone, and life after youtube?",
length: Some(775),
@ -83,7 +85,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -93,17 +95,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 528795,
view_count: Some(528795),
is_live: false,
is_short: false,
short_description: "So many questions I wasn\'t able to answer, but if you comment below I\'ll try and answer every single one of them!!!! A little bit of\u{a0}...",
is_upcoming: false,
short_description: Some("So many questions I wasn\'t able to answer, but if you comment below I\'ll try and answer every single one of them!!!! A little bit of\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "GvutfmW26JQ",
title: "👹stay sour 🍋",
length: Some(52),
@ -114,7 +117,7 @@ Paginator(
height: 720,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -124,17 +127,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 days ago"),
view_count: 1096055,
view_count: Some(1096055),
is_live: false,
is_short: true,
short_description: "Ingredients: ** Citrus Filling** 1 cup mandarin juice or any orange-y citrus in season! 6 eggs 1 1/2 cup sugar ⅓ cup flour zest of 1\u{a0}...",
is_upcoming: false,
short_description: Some("Ingredients: ** Citrus Filling** 1 cup mandarin juice or any orange-y citrus in season! 6 eggs 1 1/2 cup sugar ⅓ cup flour zest of 1\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "gK-jLnvVsb0",
title: "Contradicting myself",
length: Some(1381),
@ -150,7 +154,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -160,17 +164,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 months ago"),
view_count: 928968,
view_count: Some(928968),
is_live: false,
is_short: false,
short_description: "Sesame Granola Recipe 2 cups old-fashioned instant oats 2 cups mixture of seeds / nuts of your choice (I used ½ cup each of\u{a0}...",
is_upcoming: false,
short_description: Some("Sesame Granola Recipe 2 cups old-fashioned instant oats 2 cups mixture of seeds / nuts of your choice (I used ½ cup each of\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "NudTbo2CJMY",
title: "Flying to London",
length: Some(1078),
@ -186,7 +191,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -196,17 +201,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 1137138,
view_count: Some(1137138),
is_live: false,
is_short: false,
short_description: "Tomato Beef Curry 1 packet Japanese Curry Roux 250g thinly sliced beef 2 large onions 2 tbsp butter 2 tbsp neutral oil 1 can\u{a0}...",
is_upcoming: false,
short_description: Some("Tomato Beef Curry 1 packet Japanese Curry Roux 250g thinly sliced beef 2 large onions 2 tbsp butter 2 tbsp neutral oil 1 can\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "Nc0HzyDRjm0",
title: "Stekki-don ㅣ After Hours ep.2",
length: Some(749),
@ -222,7 +228,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -232,17 +238,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 months ago"),
view_count: 462437,
view_count: Some(462437),
is_live: false,
is_short: false,
short_description: "Stekki-Don (for two, or for one very hungry person) 500g Ribeye 1 tsp Kosher salt 2 tbsp unsalted butter Sauce 4 tbsp light soy\u{a0}...",
is_upcoming: false,
short_description: Some("Stekki-Don (for two, or for one very hungry person) 500g Ribeye 1 tsp Kosher salt 2 tbsp unsalted butter Sauce 4 tbsp light soy\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "pvSWHm4wlxY",
title: "having kids",
length: Some(60),
@ -253,7 +260,7 @@ Paginator(
height: 720,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -263,17 +270,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 11285067,
view_count: Some(11285067),
is_live: false,
is_short: true,
short_description: "shorts Instagram @doobydobap Join my discord! https://discord.gg/doobyverse www.doobydobap.com for recipes & stories.",
is_upcoming: false,
short_description: Some("shorts Instagram @doobydobap Join my discord! https://discord.gg/doobyverse www.doobydobap.com for recipes & stories."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "fGQUWI4o__A",
title: "Baskin Robbins in South Korea",
length: Some(53),
@ -284,7 +292,7 @@ Paginator(
height: 720,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -294,17 +302,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 2415040,
view_count: Some(2415040),
is_live: false,
is_short: true,
short_description: "shorts #icecream Instagram @doobydobap Join my discord! https://discord.gg/doobyverse www.doobydobap.com for recipes\u{a0}...",
is_upcoming: false,
short_description: Some("shorts #icecream Instagram @doobydobap Join my discord! https://discord.gg/doobyverse www.doobydobap.com for recipes\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "GuyGyzZcumI",
title: "McDonald\'s Michelin Burger",
length: Some(59),
@ -315,7 +324,7 @@ Paginator(
height: 720,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -325,17 +334,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 5100787,
view_count: Some(5100787),
is_live: false,
is_short: true,
short_description: "mcdonalds #michelin #fastfood Instagram @doobydobap Join my discord! https://discord.gg/doobyverse\u{a0}...",
is_upcoming: false,
short_description: Some("mcdonalds #michelin #fastfood Instagram @doobydobap Join my discord! https://discord.gg/doobyverse\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "6VGG19W08UQ",
title: "Nostalgia is a powerful ingredient",
length: Some(52),
@ -346,7 +356,7 @@ Paginator(
height: 480,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -356,17 +366,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("10 months ago"),
view_count: 55308394,
view_count: Some(55308394),
is_live: false,
is_short: true,
short_description: "shorts ASMR version on my Instagram @doobydobap Join my discord! https://discord.gg/doobyverse www.doobydobap.com\u{a0}...",
is_upcoming: false,
short_description: Some("shorts ASMR version on my Instagram @doobydobap Join my discord! https://discord.gg/doobyverse www.doobydobap.com\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "p3Xhx6aQEXo",
title: "Jjajangmyun ㅣ Doob Gourmand ep.2",
length: Some(664),
@ -382,7 +393,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -392,17 +403,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 months ago"),
view_count: 774061,
view_count: Some(774061),
is_live: false,
is_short: false,
short_description: "Stay on for bloopers! Vlog coming on Tuesday!! Location 의천각 Uicheongag 수정구 신흥동 6907번지 성남시 경기도 KR\u{a0}...",
is_upcoming: false,
short_description: Some("Stay on for bloopers! Vlog coming on Tuesday!! Location 의천각 Uicheongag 수정구 신흥동 6907번지 성남시 경기도 KR\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "35Gu3Q6qEn4",
title: "Deal Breakers",
length: Some(60),
@ -413,7 +425,7 @@ Paginator(
height: 480,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -423,17 +435,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 months ago"),
view_count: 12314192,
view_count: Some(12314192),
is_live: false,
is_short: true,
short_description: "shorts another deal breaker: people who like chocolate chip banana bread over regular-- you heard me Recipe: Wet: 3 very ripe\u{a0}...",
is_upcoming: false,
short_description: Some("shorts another deal breaker: people who like chocolate chip banana bread over regular-- you heard me Recipe: Wet: 3 very ripe\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "JoUdBrUpBN0",
title: "Jjambbong, jjajangmyeon\'s biggest rival",
length: Some(56),
@ -444,7 +457,7 @@ Paginator(
height: 480,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -454,17 +467,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 4266748,
view_count: Some(4266748),
is_live: false,
is_short: true,
short_description: "shorts Recipe on my website at www.doobydobap.com/recipe.",
is_upcoming: false,
short_description: Some("shorts Recipe on my website at www.doobydobap.com/recipe."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "l76ovWsPLi8",
title: "Jjagglee, Ricotta Persimmon Toast, Plants, and Pringles! l Home Alone All Day Vlog",
length: Some(673),
@ -480,7 +494,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -490,17 +504,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("9 months ago"),
view_count: 439888,
view_count: Some(439888),
is_live: false,
is_short: false,
short_description: "Ingredients for jjaglee 1 cup pork belly 1 cup fermented kimchi ½ onion 1 leek 1 firm tofu 1.5 tbsp gochujang 2 tbsp coarse\u{a0}...",
is_upcoming: false,
short_description: Some("Ingredients for jjaglee 1 cup pork belly 1 cup fermented kimchi ½ onion 1 leek 1 firm tofu 1.5 tbsp gochujang 2 tbsp coarse\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "zt1Lx9L619w",
title: "The biggest privilege my rich friends have",
length: Some(58),
@ -511,7 +526,7 @@ Paginator(
height: 480,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -521,16 +536,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 9312774,
view_count: Some(9312774),
is_live: false,
is_short: true,
short_description: "shorts #japanese #curry Tomato Beef Curry 1 packet Japanese Curry Roux 250g thinly sliced beef 2 large onions 2 tbsp butter 2\u{a0}...",
is_upcoming: false,
short_description: Some("shorts #japanese #curry Tomato Beef Curry 1 packet Japanese Curry Roux 250g thinly sliced beef 2 large onions 2 tbsp butter 2\u{a0}..."),
)),
],
ctoken: Some("EpMDEgpkb29ieWRvYmFwGoQDU0NpQ0FRdE9OVUZMVVdac1N6RlVWWUlCQzA5NlNVWkJURkZmV1hSQmdnRUxjako1WlRaNlZ6QnVZazJDQVF0NldVaENNemhWYkhwRk1JSUJDMGQyZFhSbWJWY3lOa3BSZ2dFTFVuSnZXWEJNZUhoT2FsbUNBUXRzTkRkUmRYVmtjMW96TklJQkMyZExMV3BNYm5aV2MySXdnZ0VMVG5Wa1ZHSnZNa05LVFZtQ0FRdE9ZekJJZW5sRVVtcHRNSUlCQzNCMlUxZEliVFIzYkhoWmdnRUxaa2RSVlZkSk5HOWZYMEdDQVF0UWVFZHRVRFIyWDBFek9JSUJDMGQxZVVkNWVscGpkVzFKZ2dFTE5sWkhSekU1VnpBNFZWR0NBUXR3TTFob2VEWmhVVVZZYjRJQkN6TTFSM1V6VVRaeFJXNDBnZ0VMU205VlpFSnlWWEJDVGpDQ0FRdHNOelp2ZGxkelVFeHBPSUlCQzNwME1VeDRPVXcyTVRsM3NnRUdDZ1FJSnhBRBiB4OgYIgtzZWFyY2gtZmVlZA%3D%3D"),
endpoint: browse,
)

View file

@ -1,11 +1,11 @@
---
source: src/client/trends.rs
source: src/client/pagination.rs
expression: map_res.c
---
Paginator(
count: None,
items: [
SearchVideo(
Video(VideoItem(
id: "mRmlXh7Hams",
title: "Extra 3 vom 12.10.2022 im NDR | extra 3 | NDR",
length: Some(1839),
@ -16,7 +16,7 @@ Paginator(
height: 270,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCjhkuC_Pi85wGjnB0I1ydxw",
name: "extra 3",
avatar: [
@ -26,17 +26,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 days ago"),
view_count: 585257,
view_count: Some(585257),
is_live: false,
is_short: false,
short_description: "Niedersachsen nach der Wahl: Schuld ist immer die Ampel | Die Grünen: Partei der erneuerbaren Prinzipien | Verhütung? Ist Frauensache! | Youtube: Handwerk mit goldenem Boden - Christian Ehring...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Niedersachsen nach der Wahl: Schuld ist immer die Ampel | Die Grünen: Partei der erneuerbaren Prinzipien | Verhütung? Ist Frauensache! | Youtube: Handwerk mit goldenem Boden - Christian Ehring..."),
)),
Video(VideoItem(
id: "LsXC5r64Pvc",
title: "Most Rarest Plays In Baseball History",
length: Some(1975),
@ -47,7 +48,7 @@ Paginator(
height: 270,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCRfKJZ7LHueFudiDgAJDr9Q",
name: "Top All Sports",
avatar: [
@ -57,17 +58,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 985521,
view_count: Some(985521),
is_live: false,
is_short: false,
short_description: "#baseball #mlb #mlbb",
),
SearchVideo(
is_upcoming: false,
short_description: Some("#baseball #mlb #mlbb"),
)),
Video(VideoItem(
id: "dwPmd1GqQHE",
title: "90S RAP & HIPHOP MIX - Notorious B I G , Dr Dre, 50 Cent, Snoop Dogg, 2Pac, DMX, Lil Jon and more",
length: Some(5457),
@ -78,7 +80,7 @@ Paginator(
height: 270,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCKICAAGtBLJJ5zRdIxn_B4g",
name: "#Hip Hop 2022",
avatar: [
@ -88,17 +90,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 months ago"),
view_count: 1654055,
view_count: Some(1654055),
is_live: false,
is_short: false,
short_description: "",
),
SearchVideo(
is_upcoming: false,
short_description: None,
)),
Video(VideoItem(
id: "qxI-Ob8lpLE",
title: "Schlatt\'s Chips Tier List",
length: Some(1071),
@ -114,7 +117,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2mP7il3YV7TxM_3m6U0bwA",
name: "jschlattLIVE",
avatar: [
@ -124,17 +127,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 9029628,
view_count: Some(9029628),
is_live: false,
is_short: false,
short_description: "Schlatt ranks every chip ever made.\nCREATE YOUR OWN TIER LIST: https://tiermaker.com/create/chips-for-big-guy-1146620\n\nSubscribe to me on Twitch:\nhttps://twitch.tv/jschlatt\n\nFollow me on Twitter:...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Schlatt ranks every chip ever made.\nCREATE YOUR OWN TIER LIST: https://tiermaker.com/create/chips-for-big-guy-1146620\n\nSubscribe to me on Twitch:\nhttps://twitch.tv/jschlatt\n\nFollow me on Twitter:..."),
)),
Video(VideoItem(
id: "qmrzTUmZ4UU",
title: "850€ für den Verrat am System - UCS AT-AT LEGO® Star Wars 75313",
length: Some(2043),
@ -150,7 +154,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC_EZd3lsmxudu3IQzpTzOgw",
name: "Held der Steine Inh. Thomas Panke",
avatar: [
@ -160,17 +164,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 days ago"),
view_count: 600516,
view_count: Some(600516),
is_live: false,
is_short: false,
short_description: "Star Wars - erschienen 2021 - 6749 Teile\n\nDieses Set bei Amazon*:\nhttps://amzn.to/3yu9dHX\n\nErwähnt im Video*:\nTassen https://bit.ly/HdSBausteinecke\nBig Boy https://bit.ly/BBLokBigBoy\nBurg...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Star Wars - erschienen 2021 - 6749 Teile\n\nDieses Set bei Amazon*:\nhttps://amzn.to/3yu9dHX\n\nErwähnt im Video*:\nTassen https://bit.ly/HdSBausteinecke\nBig Boy https://bit.ly/BBLokBigBoy\nBurg..."),
)),
Video(VideoItem(
id: "4q4vpQCIZ6w",
title: "🌉 Manhattan Jazz 💖 l Relaxing Jazz Piano Music l Background Music",
length: Some(23229),
@ -186,7 +191,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCBnMxlW70f0SB4ZTJx124lw",
name: "몽키비지엠 MONKEYBGM",
avatar: [
@ -196,17 +201,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 2343407,
view_count: Some(2343407),
is_live: false,
is_short: false,
short_description: "- Please Subscribe!\n\n🔺Disney OST Collection part 1 \n ➡\u{fe0f} https://youtu.be/lrzKFu85nhE\n\n🔺Disney OST Collection part 2 \n ➡\u{fe0f} https://youtu.be/EtE09lowIbk\n\n🔺Studio Ghibli...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("- Please Subscribe!\n\n🔺Disney OST Collection part 1 \n ➡\u{fe0f} https://youtu.be/lrzKFu85nhE\n\n🔺Disney OST Collection part 2 \n ➡\u{fe0f} https://youtu.be/EtE09lowIbk\n\n🔺Studio Ghibli..."),
)),
Video(VideoItem(
id: "Z_k31kqZxaE",
title: "1 in 1,000,000 NBA Moments",
length: Some(567),
@ -222,7 +228,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCpyoYVlp67N16Lg1_N4VnVw",
name: "dime",
avatar: [
@ -232,17 +238,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 4334298,
view_count: Some(4334298),
is_live: false,
is_short: false,
short_description: "• Instagram - https://instagram.com/dime_nba\n• TikTok - https://tiktok.com/@dime_nba\n\ndime is a Swedish brand, founded in 2022. We produce some of the most entertaining NBA content on YouTube...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("• Instagram - https://instagram.com/dime_nba\n• TikTok - https://tiktok.com/@dime_nba\n\ndime is a Swedish brand, founded in 2022. We produce some of the most entertaining NBA content on YouTube..."),
)),
Video(VideoItem(
id: "zE-a5eqvlv8",
title: "Dua Lipa, Coldplay, Martin Garrix & Kygo, The Chainsmokers Style - Feeling Me",
length: None,
@ -258,7 +265,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCX-USfenzQlhrEJR1zD5IYw",
name: "Deep Mood.",
avatar: [
@ -268,17 +275,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 889,
is_live: false,
view_count: Some(889),
is_live: true,
is_short: false,
short_description: "#Summermix #DeepHouse #DeepHouseSummerMix\nDua Lipa, Coldplay, Martin Garrix & Kygo, The Chainsmokers Style - Feeling Me\n\n🎵 All songs in this spotify playlist: https://spoti.fi/2TJ4Dyj\nSubmit...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("#Summermix #DeepHouse #DeepHouseSummerMix\nDua Lipa, Coldplay, Martin Garrix & Kygo, The Chainsmokers Style - Feeling Me\n\n🎵 All songs in this spotify playlist: https://spoti.fi/2TJ4Dyj\nSubmit..."),
)),
Video(VideoItem(
id: "gNlOk0LXi5M",
title: "Soll ich dir 1g GOLD schenken? oder JEMAND anderen DOPPELT?",
length: Some(704),
@ -294,7 +302,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCqcWNPTUVATZt0Dlr2jV0Wg",
name: "Mois",
avatar: [
@ -304,17 +312,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 days ago"),
view_count: 463834,
view_count: Some(463834),
is_live: false,
is_short: false,
short_description: "Je mehr Menschen mich abonnieren desto mehr Menschen werde ich glücklich machen \n\n24 std ab, viel Glück \n\nhttps://I-Clip.com/?sPartner=Mois",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Je mehr Menschen mich abonnieren desto mehr Menschen werde ich glücklich machen \n\n24 std ab, viel Glück \n\nhttps://I-Clip.com/?sPartner=Mois"),
)),
Video(VideoItem(
id: "dbMvZjs8Yc8",
title: "Brad Pitt- Die Revanche eines Sexsymbols | Doku HD | ARTE",
length: Some(3137),
@ -330,7 +339,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCsygZtQQSplGF6JA3XWvsdg",
name: "Irgendwas mit ARTE und Kultur",
avatar: [
@ -340,17 +349,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 days ago"),
view_count: 293878,
view_count: Some(293878),
is_live: false,
is_short: false,
short_description: "Vom „People“-Magazin wurde er mehrfach zum „Sexiest Man Alive“ gekrönt. Aber sein Aussehen ist nicht alles: In 30 Jahren Karriere drehte Brad Pitt eine Vielzahl herausragender Filme....",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Vom „People“-Magazin wurde er mehrfach zum „Sexiest Man Alive“ gekrönt. Aber sein Aussehen ist nicht alles: In 30 Jahren Karriere drehte Brad Pitt eine Vielzahl herausragender Filme...."),
)),
Video(VideoItem(
id: "mFxi3lOAcFs",
title: "Craziest Soviet Machines You Won\'t Believe Exist - Part 1",
length: Some(1569),
@ -366,7 +376,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCkQO3QsgTpNTsOw6ujimT5Q",
name: "BE AMAZED",
avatar: [
@ -376,17 +386,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 14056843,
view_count: Some(14056843),
is_live: false,
is_short: false,
short_description: "Coming up are some crazy Soviet-era machines you won\'t believe exist!\nPart 2: https://youtu.be/MBZVOJrhuHY\nSuggest a topic here to be turned into a video: http://bit.ly/2kwqhuh\nSubscribe for...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Coming up are some crazy Soviet-era machines you won\'t believe exist!\nPart 2: https://youtu.be/MBZVOJrhuHY\nSuggest a topic here to be turned into a video: http://bit.ly/2kwqhuh\nSubscribe for..."),
)),
Video(VideoItem(
id: "eu7ubm7g59E",
title: "People Hated Me For Using This Slab",
length: Some(1264),
@ -402,7 +413,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC6I0KzAD7uFTL1qzxyunkvA",
name: "Blacktail Studio",
avatar: [
@ -412,17 +423,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 2845035,
view_count: Some(2845035),
is_live: false,
is_short: false,
short_description: "Some people were furious I used this slab, and I actually understand why. \nBlacktail bow tie jig (limited first run): https://www.blacktailstudio.com/bowtie-jig\nBlacktail epoxy table workshop:...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Some people were furious I used this slab, and I actually understand why. \nBlacktail bow tie jig (limited first run): https://www.blacktailstudio.com/bowtie-jig\nBlacktail epoxy table workshop:..."),
)),
Video(VideoItem(
id: "TRGHIN2PGIA",
title: "Christian Bale Breaks Down His Most Iconic Characters | GQ",
length: Some(1381),
@ -438,7 +450,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCsEukrAd64fqA7FjwkmZ_Dw",
name: "GQ",
avatar: [
@ -448,17 +460,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("9 days ago"),
view_count: 8044465,
view_count: Some(8044465),
is_live: false,
is_short: false,
short_description: "Christian Bale breaks down a few of his most iconic characters from \'American Psycho,\' \'The Dark Knight\' Trilogy, \'The Fighter,\' \'The Machinist,\' \'The Big Short,\' \'Vice,\' \'Empire of the Sun,\'...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Christian Bale breaks down a few of his most iconic characters from \'American Psycho,\' \'The Dark Knight\' Trilogy, \'The Fighter,\' \'The Machinist,\' \'The Big Short,\' \'Vice,\' \'Empire of the Sun,\'..."),
)),
Video(VideoItem(
id: "w3tENzcssDU",
title: "NFL Trick Plays But They Get Increasingly Higher IQ",
length: Some(599),
@ -474,7 +487,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCJka5SDh36_N4pjJd69efkg",
name: "Savage Brick Sports",
avatar: [
@ -484,17 +497,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 1172372,
view_count: Some(1172372),
is_live: false,
is_short: false,
short_description: "NFL Trick Plays But They Get Increasingly Higher IQ\nCredit to CoshReport for starting this trend.\n\n(if any of the links don\'t work, check most recent video)\nTalkSports Discord: https://discord.gg/n...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("NFL Trick Plays But They Get Increasingly Higher IQ\nCredit to CoshReport for starting this trend.\n\n(if any of the links don\'t work, check most recent video)\nTalkSports Discord: https://discord.gg/n..."),
)),
Video(VideoItem(
id: "gUAd2XXzH7w",
title: "⚓\u{fe0f}Found ABANDONED SHIP!!! Big CRUISE SHIP on a desert island☠\u{fe0f} Where did the people go?!?",
length: Some(2949),
@ -510,7 +524,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UClUZos7yKYtrmr0-azaD8pw",
name: "Kreosan English",
avatar: [
@ -520,17 +534,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 1883533,
view_count: Some(1883533),
is_live: false,
is_short: false,
short_description: "We are preparing a continuation of the cruise ship for you! Very soon you will be able to see the next part. If you would like to help us make a video:\n\n► Support us - https://www.patreon.com/k...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("We are preparing a continuation of the cruise ship for you! Very soon you will be able to see the next part. If you would like to help us make a video:\n\n► Support us - https://www.patreon.com/k..."),
)),
Video(VideoItem(
id: "YpGjaJ1ettI",
title: "[Working BGM] Comfortable music that makes you feel positive -- Morning Mood -- Daily Routine",
length: Some(3651),
@ -546,7 +561,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCpxY9-3iB5Hyho31uBgzh7w",
name: "Daily Routine",
avatar: [
@ -556,17 +571,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 1465389,
view_count: Some(1465389),
is_live: false,
is_short: false,
short_description: "Hello everyone. It\'s me again. I will stay at home and study . It\'s full of fun energy today, so it\'s ready to spread to everyone with hilarious music. 🔥🔥🔥\nHave fun together 😊😊😊...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Hello everyone. It\'s me again. I will stay at home and study . It\'s full of fun energy today, so it\'s ready to spread to everyone with hilarious music. 🔥🔥🔥\nHave fun together 😊😊😊..."),
)),
Video(VideoItem(
id: "rPAhFD8hKxQ",
title: "Survival Camping 9ft/3m Under Snow - Giant Winter Bushcraft Shelter and Quinzee",
length: Some(1301),
@ -582,7 +598,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCfpCQ89W9wjkHc8J_6eTbBg",
name: "Outdoor Boys",
avatar: [
@ -592,17 +608,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 20488431,
view_count: Some(20488431),
is_live: false,
is_short: false,
short_description: "Solo winter camping and bushcraft 9 feet (3 meters) under the snow. I hiked high up into the mountains during a snow storm with 30 mph/48 kmh winds to build a deep snow bushcraft survival shelter...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Solo winter camping and bushcraft 9 feet (3 meters) under the snow. I hiked high up into the mountains during a snow storm with 30 mph/48 kmh winds to build a deep snow bushcraft survival shelter..."),
)),
Video(VideoItem(
id: "2rye4u-cCNk",
title: "Pink Panther Fights Off Pests | 54 Minute Compilation | The Pink Panther Show",
length: Some(3158),
@ -618,7 +635,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCFeUyPY6W8qX8w2o6oSiRmw",
name: "Official Pink Panther",
avatar: [
@ -628,17 +645,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 months ago"),
view_count: 27357653,
view_count: Some(27357653),
is_live: false,
is_short: false,
short_description: "(1) Pink Pest Control\n(2) Pink-a-Boo\n(3) Little Beaux Pink\n(4) The Pink Package Plot\n(5) Come On In! The Water\'s Pink\n(6) Psychedelic Pink\n(7) Pink Posies\n(8) G.I. Pink\n\nThe Pink Panther is...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("(1) Pink Pest Control\n(2) Pink-a-Boo\n(3) Little Beaux Pink\n(4) The Pink Package Plot\n(5) Come On In! The Water\'s Pink\n(6) Psychedelic Pink\n(7) Pink Posies\n(8) G.I. Pink\n\nThe Pink Panther is..."),
)),
Video(VideoItem(
id: "O0xAlfSaBNQ",
title: "FC Nantes vs. SC Freiburg Highlights & Tore | UEFA Europa League",
length: Some(326),
@ -654,7 +672,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC8WYi3XQXsf-6FNvqoEvxag",
name: "RTL Sport",
avatar: [
@ -664,17 +682,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 hours ago"),
view_count: 117395,
view_count: Some(117395),
is_live: false,
is_short: false,
short_description: "UEFA Europa League: https://www.rtlplus.com/shows/uefa-europa-league-19818?utm_source=youtube&utm_medium=editorial&utm_campaign=beschreibung&utm_term=rtlsport \nFC Nantes vs. SC Freiburg ...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("UEFA Europa League: https://www.rtlplus.com/shows/uefa-europa-league-19818?utm_source=youtube&utm_medium=editorial&utm_campaign=beschreibung&utm_term=rtlsport \nFC Nantes vs. SC Freiburg ..."),
)),
Video(VideoItem(
id: "Mhs9Sbnw19o",
title: "Dramatisches Duell: 400 Jahre altes Kästchen erzielt zig-fachen Wunschpreis! | Bares für Rares XXL",
length: Some(744),
@ -690,7 +709,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC53bIpnef1pwAx69ERmmOLA",
name: "Bares für Rares",
avatar: [
@ -700,17 +719,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 days ago"),
view_count: 836333,
view_count: Some(836333),
is_live: false,
is_short: false,
short_description: "Du hast Schätze im Keller, die du unseren Expert*innen präsentieren möchtest? Hier geht\'s zum Bewerbungsformular: kurz.zdf.de/lSJ/\n\nEin einmaliges Bieterduell treibt den Preis für dieses...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Du hast Schätze im Keller, die du unseren Expert*innen präsentieren möchtest? Hier geht\'s zum Bewerbungsformular: kurz.zdf.de/lSJ/\n\nEin einmaliges Bieterduell treibt den Preis für dieses..."),
)),
Video(VideoItem(
id: "Bzzp5Cay7DI",
title: "Sweet Jazz - Cool autumn Bossa Nova & October Jazz Positive Mood",
length: None,
@ -726,7 +746,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCoGlllJE7aYe_VzIGP3s_wA",
name: "Smooth Jazz Music",
avatar: [
@ -736,17 +756,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 1216,
is_live: false,
view_count: Some(1216),
is_live: true,
is_short: false,
short_description: "Sweet Jazz - Cool autumn Bossa Nova & October Jazz Positive Mood\nhttps://youtu.be/Bzzp5Cay7DI\n********************************************\nSounds available on: Jazz Bossa Nova\nOFFICIAL VIDEO:...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Sweet Jazz - Cool autumn Bossa Nova & October Jazz Positive Mood\nhttps://youtu.be/Bzzp5Cay7DI\n********************************************\nSounds available on: Jazz Bossa Nova\nOFFICIAL VIDEO:..."),
)),
Video(VideoItem(
id: "SlskTqc9CEc",
title: "The Chick-Fil-A Full Menu Challenge",
length: Some(613),
@ -762,7 +783,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCd1fLoVFooPeWqCEYVUJZqg",
name: "Matt Stonie",
avatar: [
@ -772,17 +793,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 39286403,
view_count: Some(39286403),
is_live: false,
is_short: false,
short_description: "Good Video? Like/Fav & Share!!\n\nTBH this is really my 1st time trying Chick-Fil-A, legitimately. My verdict is torn, but that sauce is BOMB!\n\nChallenge\n+ Chick-Fil-A Deluxe\n+ Spicy Deluxe\n+...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("Good Video? Like/Fav & Share!!\n\nTBH this is really my 1st time trying Chick-Fil-A, legitimately. My verdict is torn, but that sauce is BOMB!\n\nChallenge\n+ Chick-Fil-A Deluxe\n+ Spicy Deluxe\n+..."),
)),
Video(VideoItem(
id: "CwRvM2TfYbs",
title: "Gentle healing music of health and to calm the nervous system, deep relaxation! Say Life Yes",
length: None,
@ -798,7 +820,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC6jH5GNi0iOR17opA1Vowhw",
name: "Lucid Dream",
avatar: [
@ -808,17 +830,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 1416,
is_live: false,
view_count: Some(1416),
is_live: true,
is_short: false,
short_description: "🌿 Music for relaxation, meditation, study, reading, massage, spa or sleep. This music is ideal for dealing with anxiety, stress or insomnia as it promotes relaxation and helps eliminate...",
),
SearchVideo(
is_upcoming: false,
short_description: Some("🌿 Music for relaxation, meditation, study, reading, massage, spa or sleep. This music is ideal for dealing with anxiety, stress or insomnia as it promotes relaxation and helps eliminate..."),
)),
Video(VideoItem(
id: "7jz0pXSe_kI",
title: "Craziest \"Fine...I\'ll Do it Myself\" Moments in Sports History (PART 2)",
length: Some(1822),
@ -834,7 +857,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCd5hdemikI6GxwGKhJCwzww",
name: "Highlight Reel",
avatar: [
@ -844,16 +867,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("10 months ago"),
view_count: 11601863,
view_count: Some(11601863),
is_live: false,
is_short: false,
short_description: "(PART 2) of 👉🏼 Craziest \"Fine...I\'ll Do It Myself\" Moments in Sports History \n\nBIBLE VERSE OF THE DAY: Luke 12:40",
),
is_upcoming: false,
short_description: Some("(PART 2) of 👉🏼 Craziest \"Fine...I\'ll Do It Myself\" Moments in Sports History \n\nBIBLE VERSE OF THE DAY: Luke 12:40"),
)),
],
ctoken: Some("4qmFsgKxAxIPRkV3aGF0X3RvX3dhdGNoGoADQ0RCNmxnSkhUWFpRYzJOVU1UUm1iME5OWjNOSmQzWjZOM0JPWlZWMldqZDFRVlp3ZEVOdGMwdEhXR3d3V0ROQ2FGb3lWbVpqTWpWb1kwaE9iMkl6VW1aamJWWnVZVmM1ZFZsWGQxTklNVlUwVDFSU1dXUXhUbXhXTTBaeVdsaGtSRkpGYkZCWk0yaDZWbXMxTlV4VmVGbE1XRnBSVlcxallVeFJRVUZhVnpSQlFWWldWRUZCUmtWU1VVRkNRVVZhUm1ReWFHaGtSamt3WWpFNU0xbFlVbXBoUVVGQ1FVRkZRa0ZCUVVKQlFVVkJRVUZGUWtGSFNrSkRRVUZUUlROQ2FGb3lWbVpqTWpWb1kwaE9iMkl6VW1aa1J6bHlXbGMwWVVWM2Ftb3hPRkJGT1dWSU5rRm9WVlpZWlVGTFNGaHVSMEp2ZDJsRmQycERObkZmUlRsbFNEWkJhRmRIZG1RMFMwaGxaMGhDTlZnMmJrMWxPVU5SU1VsTlVRJTNEJTNEmgIaYnJvd3NlLWZlZWRGRXdoYXRfdG9fd2F0Y2g%3D"),
endpoint: browse,
)

File diff suppressed because it is too large Load diff

View file

@ -3110,6 +3110,7 @@ Playlist(
),
],
ctoken: Some("4qmFsgJhEiRWTFBMNWREeDY4MVQ0YlI3WkYxSXVXek92MW9tbFJiRTdQaUoaFENBRjZCbEJVT2tOSFdRJTNEJTNEmgIiUEw1ZER4NjgxVDRiUjdaRjFJdVd6T3Yxb21sUmJFN1BpSg%3D%3D"),
endpoint: browse,
),
video_count: 495,
thumbnail: [

View file

@ -2056,6 +2056,7 @@ Playlist(
),
],
ctoken: None,
endpoint: browse,
),
video_count: 66,
thumbnail: [

View file

@ -3017,6 +3017,7 @@ Playlist(
),
],
ctoken: None,
endpoint: browse,
),
video_count: 97,
thumbnail: [

View file

@ -6,7 +6,7 @@ SearchResult(
items: Paginator(
count: Some(7499),
items: [
Channel(SearchChannel(
Channel(ChannelItem(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -21,12 +21,12 @@ SearchResult(
height: 176,
),
],
verification: verified,
verification: Verified,
subscriber_count: Some(292),
video_count: 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}...",
)),
Video(SearchVideo(
Video(VideoItem(
id: "1VW7iXRIrc8",
title: "Alone, in the City of Love",
length: Some(1875),
@ -42,7 +42,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -52,17 +52,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 531580,
view_count: Some(531580),
is_live: false,
is_short: false,
short_description: "I know it\'s a little long, but I hope you enjoyed this Paris vlog :} Location Udon Restaurant: Sanukiya 9 Rue d\'Argenteuil, Paris\u{a0}...",
is_upcoming: false,
short_description: Some("I know it\'s a little long, but I hope you enjoyed this Paris vlog :} Location Udon Restaurant: Sanukiya 9 Rue d\'Argenteuil, Paris\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "9NuhKCv3crg",
title: "the end.",
length: Some(982),
@ -78,7 +79,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -88,17 +89,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 days ago"),
view_count: 974475,
view_count: Some(974475),
is_live: false,
is_short: false,
short_description: "or the start of something new~~~~~ Thank you for your patience on the vlog, it took some time to adjust to my new normal. Excited\u{a0}...",
is_upcoming: false,
short_description: Some("or the start of something new~~~~~ Thank you for your patience on the vlog, it took some time to adjust to my new normal. Excited\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "hGbQ2WM9nOo",
title: "Why does everything bad for you taste good ㅣ CHILI OIL RAMEN",
length: Some(428),
@ -114,7 +116,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -124,17 +126,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 1034415,
view_count: Some(1034415),
is_live: false,
is_short: false,
short_description: "https://partner.bokksu.com/doobydobap use code DOOBYDOBAP to get $15 off your first bokksu order! Instagram @doobydobap\u{a0}...",
is_upcoming: false,
short_description: Some("https://partner.bokksu.com/doobydobap use code DOOBYDOBAP to get $15 off your first bokksu order! Instagram @doobydobap\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "PxGmP4v_A38",
title: "Alone and Thriving l late night korean convenience store, muji kitchenware haul, spring cleaning!",
length: Some(1437),
@ -150,7 +153,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -160,17 +163,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 831908,
view_count: Some(831908),
is_live: false,
is_short: false,
short_description: "I could palpably feel how I\'m so much happier than before when I was reviewing my footage All the finalized recipes will be\u{a0}...",
is_upcoming: false,
short_description: Some("I could palpably feel how I\'m so much happier than before when I was reviewing my footage All the finalized recipes will be\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "38Gd6TdmNVs",
title: "KOREAN BARBECUE l doob gourmand ep.3",
length: Some(525),
@ -186,7 +190,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -196,17 +200,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 354486,
view_count: Some(354486),
is_live: false,
is_short: false,
short_description: "I haven\'t done a doob gourmand series in so so long! I hope you enjoyed it, let me know what kind of food you\'re interested in\u{a0}...",
is_upcoming: false,
short_description: Some("I haven\'t done a doob gourmand series in so so long! I hope you enjoyed it, let me know what kind of food you\'re interested in\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "CutR_1SDDzY",
title: "feels good to be back",
length: Some(1159),
@ -222,7 +227,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -232,17 +237,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 524950,
view_count: Some(524950),
is_live: false,
is_short: false,
short_description: "I missed you guys. Happy to see you guys back. I\'ve really been working on my mental health, educating myself with different food\u{a0}...",
is_upcoming: false,
short_description: Some("I missed you guys. Happy to see you guys back. I\'ve really been working on my mental health, educating myself with different food\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "pRVSdUxdsVw",
title: "Repairing...",
length: Some(965),
@ -258,7 +264,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -268,17 +274,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 weeks ago"),
view_count: 528595,
view_count: Some(528595),
is_live: false,
is_short: false,
short_description: "The word repair stems from the Latin word reparare, from re- \'back\' and parare \'make ready.\' And I feel that\'s exactly how I feel\u{a0}...",
is_upcoming: false,
short_description: Some("The word repair stems from the Latin word reparare, from re- \'back\' and parare \'make ready.\' And I feel that\'s exactly how I feel\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "KUz7oArksR4",
title: "running away",
length: Some(1023),
@ -294,7 +301,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -304,17 +311,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 717515,
view_count: Some(717515),
is_live: false,
is_short: false,
short_description: "for now... more adventures to come! Music by Mark Generous - A Summer Day - https://thmatc.co/?l=CF6C5FFF Instagram\u{a0}...",
is_upcoming: false,
short_description: Some("for now... more adventures to come! Music by Mark Generous - A Summer Day - https://thmatc.co/?l=CF6C5FFF Instagram\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "sPb2gyN-hnE",
title: "worth fighting for",
length: Some(1232),
@ -330,7 +338,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -340,17 +348,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 624386,
view_count: Some(624386),
is_live: false,
is_short: false,
short_description: "Please be respectful in the comments section! I will not be tolerating any hateful/derogatory speech *barking noise* Music\u{a0}...",
is_upcoming: false,
short_description: Some("Please be respectful in the comments section! I will not be tolerating any hateful/derogatory speech *barking noise* Music\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "rriwHj8U664",
title: "my seoul apartment tour",
length: Some(721),
@ -366,7 +375,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -376,17 +385,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 696942,
view_count: Some(696942),
is_live: false,
is_short: false,
short_description: "Korea has an interesting rent structure called junseh where you pay a higher security deposit in turn for lower rent! And before\u{a0}...",
is_upcoming: false,
short_description: Some("Korea has an interesting rent structure called junseh where you pay a higher security deposit in turn for lower rent! And before\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "PXsK9-CFoH4",
title: "waiting...",
length: Some(1455),
@ -402,7 +412,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -412,17 +422,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 923749,
view_count: Some(923749),
is_live: false,
is_short: false,
short_description: "tuna kimchi jook 2 cups cooked rice 3 cups water 1 cup kimchi 320g canned tuna 1 tbsp perilla seed oil 1 onion 1 tbsp gochujang\u{a0}...",
is_upcoming: false,
short_description: Some("tuna kimchi jook 2 cups cooked rice 3 cups water 1 cup kimchi 320g canned tuna 1 tbsp perilla seed oil 1 onion 1 tbsp gochujang\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "bXbmYelTnhw",
title: "Doobydobap rates British desserts!",
length: Some(865),
@ -438,7 +449,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOgGAfSUy5LvEyVS_LF5kdw",
name: "JOLLY",
avatar: [
@ -448,17 +459,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 1282467,
view_count: Some(1282467),
is_live: false,
is_short: false,
short_description: "Today we introduce @Doobydobap to the best of British desserts! Massive thanks to Dooby for joining us for this episode.",
is_upcoming: false,
short_description: Some("Today we introduce @Doobydobap to the best of British desserts! Massive thanks to Dooby for joining us for this episode."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "0onVbAuBGWI",
title: "Out of Control",
length: Some(1125),
@ -474,7 +486,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -484,17 +496,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 months ago"),
view_count: 1649656,
view_count: Some(1649656),
is_live: false,
is_short: false,
short_description: "Hey doobies, I know I promised a cookie recipe in my last vlog, but I haven\'t yet developed one of my own just yet-- still recipe\u{a0}...",
is_upcoming: false,
short_description: Some("Hey doobies, I know I promised a cookie recipe in my last vlog, but I haven\'t yet developed one of my own just yet-- still recipe\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "FKJtrUeol3o",
title: "with quantity comes quality",
length: Some(1140),
@ -510,7 +523,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -520,17 +533,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 months ago"),
view_count: 1085725,
view_count: Some(1085725),
is_live: false,
is_short: false,
short_description: "A busy, but calm week for me here in Seoul living alone. Planning on exploring more parts of Korea, please let me know in the\u{a0}...",
is_upcoming: false,
short_description: Some("A busy, but calm week for me here in Seoul living alone. Planning on exploring more parts of Korea, please let me know in the\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "dkMtSrjDLO0",
title: "How to make Naruto\'s favorite ramen",
length: Some(802),
@ -546,7 +560,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -556,17 +570,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("10 months ago"),
view_count: 1327833,
view_count: Some(1327833),
is_live: false,
is_short: false,
short_description: "Broth * 1 large chicken * 1 leek & ½ onion charred * 1 leek & ½ onion * 1 tbsp ginger * 6 garlic cloves Tare * leftover cha shu\u{a0}...",
is_upcoming: false,
short_description: Some("Broth * 1 large chicken * 1 leek & ½ onion charred * 1 leek & ½ onion * 1 tbsp ginger * 6 garlic cloves Tare * leftover cha shu\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "r2ye6zW0nbM",
title: "a wedding",
length: Some(1207),
@ -582,7 +597,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -592,17 +607,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 1052801,
view_count: Some(1052801),
is_live: false,
is_short: false,
short_description: "Ginger Pork Recipe! https://doobydobap.com/recipe/ginger-pork-shogayaki - Instagram @doobydobap Join my discord!",
is_upcoming: false,
short_description: Some("Ginger Pork Recipe! https://doobydobap.com/recipe/ginger-pork-shogayaki - Instagram @doobydobap Join my discord!"),
)),
Video(SearchVideo(
Video(VideoItem(
id: "NudTbo2CJMY",
title: "Flying to London",
length: Some(1078),
@ -618,7 +634,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -628,17 +644,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 1137136,
view_count: Some(1137136),
is_live: false,
is_short: false,
short_description: "Tomato Beef Curry 1 packet Japanese Curry Roux 250g thinly sliced beef 2 large onions 2 tbsp butter 2 tbsp neutral oil 1 can\u{a0}...",
is_upcoming: false,
short_description: Some("Tomato Beef Curry 1 packet Japanese Curry Roux 250g thinly sliced beef 2 large onions 2 tbsp butter 2 tbsp neutral oil 1 can\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "gK-jLnvVsb0",
title: "Contradicting myself",
length: Some(1381),
@ -654,7 +671,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -664,17 +681,18 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 months ago"),
view_count: 928967,
view_count: Some(928967),
is_live: false,
is_short: false,
short_description: "Sesame Granola Recipe 2 cups old-fashioned instant oats 2 cups mixture of seeds / nuts of your choice (I used ½ cup each of\u{a0}...",
is_upcoming: false,
short_description: Some("Sesame Granola Recipe 2 cups old-fashioned instant oats 2 cups mixture of seeds / nuts of your choice (I used ½ cup each of\u{a0}..."),
)),
Video(SearchVideo(
Video(VideoItem(
id: "fAFFTOpUNWo",
title: "Come Grocery Shopping with Me",
length: Some(1126),
@ -690,7 +708,7 @@ SearchResult(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
avatar: [
@ -700,18 +718,20 @@ SearchResult(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 months ago"),
view_count: 1077297,
view_count: Some(1077297),
is_live: false,
is_short: false,
short_description: "Pecan Banana Bread with Coffee Liquor Recipe https://doobydobap.com/recipe/pecan-banana-bread-with-coffee-liquor Music\u{a0}...",
is_upcoming: false,
short_description: Some("Pecan Banana Bread with Coffee Liquor Recipe https://doobydobap.com/recipe/pecan-banana-bread-with-coffee-liquor Music\u{a0}..."),
)),
],
ctoken: Some("EqsDEgpkb29ieWRvYmFwGpwDU0JTQ0FSaFZRMmc0WjBoa2RIcFBNblJZWkRVNU0xOWlha1Z5VjJlQ0FRc3hWbGMzYVZoU1NYSmpPSUlCQ3psT2RXaExRM1l6WTNKbmdnRUxhRWRpVVRKWFRUbHVUMi1DQVF0UWVFZHRVRFIyWDBFek9JSUJDek00UjJRMlZHUnRUbFp6Z2dFTFEzVjBVbDh4VTBSRWVsbUNBUXR3VWxaVFpGVjRaSE5XZDRJQkMwdFZlamR2UVhKcmMxSTBnZ0VMYzFCaU1tZDVUaTFvYmtXQ0FRdHljbWwzU0dvNFZUWTJOSUlCQzFCWWMwczVMVU5HYjBnMGdnRUxZbGhpYlZsbGJGUnVhSGVDQVFzd2IyNVdZa0YxUWtkWFNZSUJDMFpMU25SeVZXVnZiRE52Z2dFTFpHdE5kRk55YWtSTVR6Q0NBUXR5TW5sbE5ucFhNRzVpVFlJQkMwNTFaRlJpYnpKRFNrMVpnZ0VMWjBzdGFreHVkbFp6WWpDQ0FRdG1RVVpHVkU5d1ZVNVhiN0lCQmdvRUNCY1FBZyUzRCUzRBiB4OgYIgtzZWFyY2gtZmVlZA%3D%3D"),
endpoint: browse,
),
corrected_query: Some("doobydobap"),
)

View file

@ -7,6 +7,7 @@ SearchResult(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
corrected_query: None,
)

View file

@ -6,7 +6,7 @@ SearchResult(
items: Paginator(
count: Some(18932046),
items: [
Playlist(SearchPlaylist(
Playlist(PlaylistItem(
id: "RDCLAK5uy_nmS3YoxSwVVQk9lEQJ0UX4ZCjXsW_psU8",
name: "Pop\'s Biggest Hits",
thumbnail: [
@ -31,21 +31,16 @@ SearchResult(
height: 188,
),
],
video_count: 225,
first_videos: [
SearchPlaylistVideo(
id: "XfEMj-z3TtA",
title: "STAY",
length: Some(142),
),
SearchPlaylistVideo(
id: "MozAXGgC1Mc",
title: "Sugar",
length: Some(236),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(225),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_mVJ3RRi_YBfUJnZnQxLAedQQcXHujbUcg",
name: "Pump-Up Pop",
thumbnail: [
@ -70,21 +65,16 @@ SearchResult(
height: 188,
),
],
video_count: 100,
first_videos: [
SearchPlaylistVideo(
id: "J7p4bzqLvCw",
title: "Blinding Lights",
length: Some(202),
),
SearchPlaylistVideo(
id: "G1ej5up7JG0",
title: "Shivers",
length: Some(208),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(100),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_mfdqvCAl8wodlx2P2_Ai2gNkiRDAufkkI",
name: "Happy Pop Hits",
thumbnail: [
@ -109,21 +99,16 @@ SearchResult(
height: 188,
),
],
video_count: 59,
first_videos: [
SearchPlaylistVideo(
id: "52QG9C9dnLM",
title: "Better Days",
length: Some(161),
),
SearchPlaylistVideo(
id: "ntG3GQdY_Ok",
title: "Light Switch",
length: Some(186),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(59),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_nHSqCJjDrW9HBhCNdF6tWPdnOMngOv0wA",
name: "Pop Gold",
thumbnail: [
@ -148,21 +133,16 @@ SearchResult(
height: 188,
),
],
video_count: 100,
first_videos: [
SearchPlaylistVideo(
id: "XqoanTj5pNY",
title: "Someone Like You",
length: Some(286),
),
SearchPlaylistVideo(
id: "th92jw2CFOA",
title: "When I Was Your Man",
length: Some(214),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(100),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_lb6CVU6S4uVugLVNTU9WhqfaomWAgnho4",
name: "Shout-Out Pop Hits",
thumbnail: [
@ -187,21 +167,16 @@ SearchResult(
height: 188,
),
],
video_count: 50,
first_videos: [
SearchPlaylistVideo(
id: "cTr-aGK-LpA",
title: "My Head & My Heart",
length: Some(175),
),
SearchPlaylistVideo(
id: "xn0-IZZ6YO4",
title: "abcdefu",
length: Some(169),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(50),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_nDL8KeBrUagwyISwNmyEiSfYgz1gVCesg",
name: "Mellow Pop Classics",
thumbnail: [
@ -226,21 +201,16 @@ SearchResult(
height: 188,
),
],
video_count: 50,
first_videos: [
SearchPlaylistVideo(
id: "fdz_cabS9BU",
title: "Thinking out Loud",
length: Some(282),
),
SearchPlaylistVideo(
id: "BRbTpCrHv4o",
title: "Broken Strings",
length: Some(251),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(50),
)),
Playlist(PlaylistItem(
id: "PLDIoUOhQQPlVr3qepMVRsDe4T8vNQsvno",
name: "Türkçe Pop Şarkılar 2022 - Yeni Hit Şarkılar 2022",
thumbnail: [
@ -265,21 +235,16 @@ SearchResult(
height: 188,
),
],
video_count: 220,
first_videos: [
SearchPlaylistVideo(
id: "zU2_jPxz9q4",
title: "Ara - Zeynep Bastık (Paro Official ZB Version) | Music Video",
length: Some(201),
),
SearchPlaylistVideo(
id: "vHIf_Gk8GLg",
title: "Mustafa Ceceli & Indira Elemes - İlla",
length: Some(153),
),
],
channel: Some(ChannelTag(
id: "UCX9oPuvJYZsG8wnHTwOBVPA",
name: "Chillax",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(220),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_nfs_t4FUu00E5ED6lveEBBX1VMYe1mFjk",
name: "Dance-Pop Bangers",
thumbnail: [
@ -304,21 +269,16 @@ SearchResult(
height: 188,
),
],
video_count: 100,
first_videos: [
SearchPlaylistVideo(
id: "hJWSZDJb-W4",
title: "Bad Habits",
length: Some(231),
),
SearchPlaylistVideo(
id: "c5l4CGQozWY",
title: "Work from Home",
length: Some(215),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(100),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_m_0U5VQNyyzwwH1lRi7cPAAGXqNQnAOqY",
name: "Laid-Back Sofa Pop",
thumbnail: [
@ -343,21 +303,16 @@ SearchResult(
height: 188,
),
],
video_count: 67,
first_videos: [
SearchPlaylistVideo(
id: "T7iuw9Qx7t4",
title: "Astronomy",
length: Some(244),
),
SearchPlaylistVideo(
id: "p-IXgwqhfmg",
title: "Love Yourself",
length: Some(234),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(67),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_mHW5bcduhjB-PkTePAe6EoRMj1xNT8gzY",
name: "K-Pop Girl Crush",
thumbnail: [
@ -382,21 +337,16 @@ SearchResult(
height: 188,
),
],
video_count: 78,
first_videos: [
SearchPlaylistVideo(
id: "18nDrsoii5M",
title: "붐바야 (Boombayah)",
length: Some(241),
),
SearchPlaylistVideo(
id: "miqQAzOXPBo",
title: "달라달라 DALLA DALLA",
length: Some(200),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(78),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_kPqJ_FiGk-lbXtgM4IF42uokskSJZiVTI",
name: "Cardio Pop",
thumbnail: [
@ -421,21 +371,16 @@ SearchResult(
height: 188,
),
],
video_count: 80,
first_videos: [
SearchPlaylistVideo(
id: "G1ej5up7JG0",
title: "Shivers",
length: Some(208),
),
SearchPlaylistVideo(
id: "vgn-b0ksX4g",
title: "Heaven Takes You Home",
length: Some(215),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(80),
)),
Playlist(PlaylistItem(
id: "PLI_7Mg2Z_-4Lf7IYeiTEOV8HBn-nMqz5N",
name: "Pop 2022 ♫ Mix Pop En Ingles (English Pop Songs 2022)",
thumbnail: [
@ -460,21 +405,16 @@ SearchResult(
height: 188,
),
],
video_count: 70,
first_videos: [
SearchPlaylistVideo(
id: "a7GITgqwDVg",
title: "Charlie Puth - Left And Right (feat. Jung Kook of BTS) [Official Video]",
length: Some(160),
),
SearchPlaylistVideo(
id: "H5v3kku4y6Q",
title: "Harry Styles - As It Was (Official Video)",
length: Some(166),
),
],
channel: Some(ChannelTag(
id: "UC8Ojfs-1VLiAO_MosLwvjpQ",
name: "Redlist - Ultimate Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(70),
)),
Playlist(PlaylistItem(
id: "PLX6L4t7t6ZanfCJ1wBxRdGZ_mk9ygmKqo",
name: "Deutsch Pop Hits NEU 2022",
thumbnail: [
@ -499,21 +439,16 @@ SearchResult(
height: 188,
),
],
video_count: 164,
first_videos: [
SearchPlaylistVideo(
id: "oE7Fe8QBw1Y",
title: "Johannes Oerding - Kaleidoskop",
length: Some(217),
),
SearchPlaylistVideo(
id: "JvqMO-tWlrU",
title: "Tim Bendzko - DAS LEBEN WIEDER LIEBEN (Offizielles Musikvideo)",
length: Some(169),
),
],
channel: Some(ChannelTag(
id: "UCesP91XKnuZVd6OJN06hokg",
name: "Startup Records",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(164),
)),
Playlist(PlaylistItem(
id: "PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj",
name: "Pop Music Playlist - Timeless Pop Songs (Updated Weekly 2022)",
thumbnail: [
@ -538,21 +473,16 @@ SearchResult(
height: 188,
),
],
video_count: 200,
first_videos: [
SearchPlaylistVideo(
id: "U0CGsw6h60k",
title: "Rihanna - What\'s My Name? ft. Drake",
length: Some(265),
),
SearchPlaylistVideo(
id: "OPf0YbXqDm0",
title: "Mark Ronson - Uptown Funk (Official Video) ft. Bruno Mars",
length: Some(271),
),
],
channel: Some(ChannelTag(
id: "UCs72iRpTEuwV3y6pdWYLgiw",
name: "Redlist - Just Hits",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(200),
)),
Playlist(PlaylistItem(
id: "PLgRdph0qPLy53IhYrQLPpATDDA2TpFey5",
name: "Teen-Pop 90-2000",
thumbnail: [
@ -577,21 +507,16 @@ SearchResult(
height: 188,
),
],
video_count: 50,
first_videos: [
SearchPlaylistVideo(
id: "4fndeDfaWCg",
title: "Backstreet Boys - I Want It That Way (Official HD Video)",
length: Some(220),
),
SearchPlaylistVideo(
id: "gJLIiF15wjQ",
title: "Spice Girls - Wannabe (Official Music Video)",
length: Some(236),
),
],
channel: Some(ChannelTag(
id: "UCv9O2E_G8U46Paz8828THJw",
name: "Victor Vaz",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(50),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_nCVF_zUZizzRcojIUuYmaXxMoPgg2WMDo",
name: "Klangfarbe: German Pop Hits",
thumbnail: [
@ -616,21 +541,16 @@ SearchResult(
height: 188,
),
],
video_count: 52,
first_videos: [
SearchPlaylistVideo(
id: "jBFcbfteBDU",
title: "Ich hass dich",
length: Some(194),
),
SearchPlaylistVideo(
id: "CjV7rkhQ66I",
title: "ROSES",
length: Some(148),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(52),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_lY6JFrs7W9yIhFjUN_yxQ_ubkjcrqQaVs",
name: "Bedroom Pop",
thumbnail: [
@ -655,21 +575,16 @@ SearchResult(
height: 188,
),
],
video_count: 178,
first_videos: [
SearchPlaylistVideo(
id: "r23tQvESL7w",
title: "Picture in my mind",
length: Some(177),
),
SearchPlaylistVideo(
id: "4DyV0hWOdQw",
title: "we fell in love in october",
length: Some(185),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(178),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_l7K78k4EkjcFojhd1617rmUjY-aet6-t0",
name: "K-Pop Party Hits",
thumbnail: [
@ -694,21 +609,16 @@ SearchResult(
height: 188,
),
],
video_count: 87,
first_videos: [
SearchPlaylistVideo(
id: "LCpjdohpuEE",
title: "Permission to Dance",
length: Some(188),
),
SearchPlaylistVideo(
id: "8mA6jIeojnk",
title: "How You Like That",
length: Some(182),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(87),
)),
Playlist(PlaylistItem(
id: "RDCLAK5uy_lj-zBExVYl7YN_NxXboDIh4A-wKGfgzNY",
name: "I-Pop Hits!",
thumbnail: [
@ -733,21 +643,16 @@ SearchResult(
height: 188,
),
],
video_count: 50,
first_videos: [
SearchPlaylistVideo(
id: "g-7u06NK1mo",
title: "Killer Haseena",
length: Some(161),
),
SearchPlaylistVideo(
id: "v0Q56geMlkk",
title: "Kesariyo Rang",
length: Some(194),
),
],
channel: Some(ChannelTag(
id: "UC-9-kyTW8ZkZNDHQJ6FgpwQ",
name: "YouTube Music",
avatar: [],
verification: None,
subscriber_count: None,
)),
Playlist(SearchPlaylist(
video_count: Some(50),
)),
Playlist(PlaylistItem(
id: "PLDIoUOhQQPlXqz5QZ3dx-lh_p6RcPeKjv",
name: "POP Music Playlist 2022 - New POP Songs - Pop Songs 2022 Playlist",
thumbnail: [
@ -772,22 +677,18 @@ SearchResult(
height: 188,
),
],
video_count: 100,
first_videos: [
SearchPlaylistVideo(
id: "WcIcVapfqXw",
title: "Rema, Selena Gomez - Calm Down (Official Music Video)",
length: Some(240),
),
SearchPlaylistVideo(
id: "a7GITgqwDVg",
title: "Charlie Puth - Left And Right (feat. Jung Kook of BTS) [Official Video]",
length: Some(160),
),
],
channel: Some(ChannelTag(
id: "UCX9oPuvJYZsG8wnHTwOBVPA",
name: "Chillax",
avatar: [],
verification: None,
subscriber_count: None,
)),
video_count: Some(100),
)),
],
ctoken: Some("EqIJEgNwb3AamglFZ0lRQTBnVWdnRXJVa1JEVEVGTE5YVjVYMjV0VXpOWmIzaFRkMVpXVVdzNWJFVlJTakJWV0RSYVEycFljMWRmY0hOVk9JSUJLMUpFUTB4QlN6VjFlVjl0VmtvelVsSnBYMWxDWmxWS2JscHVVWGhNUVdWa1VWRmpXRWgxYW1KVlkyZUNBU3RTUkVOTVFVczFkWGxmYldaa2NYWkRRV3c0ZDI5a2JIZ3lVREpmUVdreVowNXJhVkpFUVhWbWEydEpnZ0VyVWtSRFRFRkxOWFY1WDI1SVUzRkRTbXBFY2xjNVNFSm9RMDVrUmpaMFYxQmtiazlOYm1kUGRqQjNRWUlCSzFKRVEweEJTelYxZVY5c1lqWkRWbFUyVXpSMVZuVm5URlpPVkZVNVYyaHhabUZ2YlZkQloyNW9ielNDQVN0U1JFTk1RVXMxZFhsZmJrUk1PRXRsUW5KVllXZDNlVWxUZDA1dGVVVnBVMlpaWjNveFoxWkRaWE5uZ2dFaVVFeEVTVzlWVDJoUlVWQnNWbkl6Y1dWd1RWWlNjMFJsTkZRNGRrNVJjM1p1YjRJQksxSkVRMHhCU3pWMWVWOXVabk5mZERSR1ZYVXdNRVUxUlVRMmJIWmxSVUpDV0RGV1RWbGxNVzFHYW11Q0FTdFNSRU5NUVVzMWRYbGZiVjh3VlRWV1VVNTVlWHAzZDBneGJGSnBOMk5RUVVGSFdIRk9VVzVCVDNGWmdnRXJVa1JEVEVGTE5YVjVYMjFJVnpWaVkyUjFhR3BDTFZCclZHVlFRV1UyUlc5U1RXb3hlRTVVT0dkNldZSUJLMUpFUTB4QlN6VjFlVjlyVUhGS1gwWnBSMnN0YkdKWWRHZE5ORWxHTkRKMWIydHphMU5LV21sV1ZFbUNBU0pRVEVsZk4wMW5NbHBmTFRSTVpqZEpXV1ZwVkVWUFZqaElRbTR0YmsxeGVqVk9nZ0VpVUV4WU5rdzBkRGQwTmxwaGJtWkRTakYzUW5oU1pFZGFYMjFyT1hsbmJVdHhiNElCSWxCTVRVTTVTMDVyU1c1alMzUlFlbWRaTFRWeWJXaDJhamRtWVhnNFptUjRiMnFDQVNKUVRHZFNaSEJvTUhGUVRIazFNMGxvV1hKUlRGQndRVlJFUkVFeVZIQkdaWGsxZ2dFclVrUkRURUZMTlhWNVgyNURWa1pmZWxWYWFYcDZVbU52YWtsVmRWbHRZVmg0VFc5UVoyY3lWMDFFYjRJQksxSkVRMHhCU3pWMWVWOXNXVFpLUm5Kek4xYzVlVWxvUm1wVlRsOTVlRkZmZFdKcmFtTnljVkZoVm5PQ0FTdFNSRU5NUVVzMWRYbGZiRGRMTnpock5FVnJhbU5HYjJwb1pERTJNVGR5YlZWcVdTMWhaWFEyTFhRd2dnRXJVa1JEVEVGTE5YVjVYMnhxTFhwQ1JYaFdXV3czV1U1ZlRuaFlZbTlFU1dnMFFTMTNTMGRtWjNwT1dZSUJJbEJNUkVsdlZVOW9VVkZRYkZoeGVqVlJXak5rZUMxc2FGOXdObEpqVUdWTGFuYXlBUVlLQkFnVkVBSSUzRBiB4OgYIgtzZWFyY2gtZmVlZA%3D%3D"),
endpoint: browse,
),
corrected_query: None,
)

View file

@ -5,7 +5,7 @@ expression: map_res.c
Paginator(
count: None,
items: [
SearchVideo(
VideoItem(
id: "_cyJhGsXDDM",
title: "Ultimate Criminal Canal Found Magnet Fishing! Police on the Hunt",
length: Some(1096),
@ -21,7 +21,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCMLXec9-wpON8tZegnDsYLw",
name: "Bondi Treasure Hunter",
avatar: [
@ -31,17 +31,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 day ago"),
view_count: 700385,
view_count: Some(700385),
is_live: false,
is_short: false,
short_description: "Subscribe for more Treasure Hunting videos: https://tinyurl.com/yyl3zerk\n\nMy Magnet! (Use Discount code \'BONDI\'): https://magnetarmagnets.com/\nMy Dive System! (Use Bonus code \'BONDI\'): https://lddy...",
is_upcoming: false,
short_description: Some("Subscribe for more Treasure Hunting videos: https://tinyurl.com/yyl3zerk\n\nMy Magnet! (Use Discount code \'BONDI\'): https://magnetarmagnets.com/\nMy Dive System! (Use Bonus code \'BONDI\'): https://lddy..."),
),
SearchVideo(
VideoItem(
id: "36YnV9STBqc",
title: "The Good Life Radio\u{a0}•\u{a0}24/7 Live Radio | Best Relax House, Chillout, Study, Running, Gym, Happy Music",
length: None,
@ -57,7 +58,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UChs0pSaEoNLV4mevBFGaoKA",
name: "The Good Life Radio x Sensual Musique",
avatar: [
@ -67,17 +68,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 7202,
is_live: false,
view_count: Some(7202),
is_live: true,
is_short: false,
short_description: "The Good Life is live streaming the best of Relaxing & Chill House Music, Deep House, Tropical House, EDM, Dance & Pop as well as Music for Sleep, Focus, Study, Workout, Gym, Running etc. in...",
is_upcoming: false,
short_description: Some("The Good Life is live streaming the best of Relaxing & Chill House Music, Deep House, Tropical House, EDM, Dance & Pop as well as Music for Sleep, Focus, Study, Workout, Gym, Running etc. in..."),
),
SearchVideo(
VideoItem(
id: "YYD1qgH5qC4",
title: "چند شنبه با سینــا | فصل چهـارم | قسمت 5 | با حضور نازنین انصاری مدیر روزنامه کیهان لندن",
length: Some(3261),
@ -93,7 +95,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCzH_7hfL6Jd1H0WpNO_eryQ",
name: "MBC PERSIA",
avatar: [
@ -103,17 +105,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("14 hours ago"),
view_count: 104344,
view_count: Some(104344),
is_live: false,
is_short: false,
short_description: "#mbcpersia\n#chandshanbeh\n#چندشنبه\n\nشبكه ام بى سى پرشيا را از حساب هاى مختلف در شبكه هاى اجتماعى دنبال كنيد\n►MBCPERSIA on Facebook:...",
is_upcoming: false,
short_description: Some("#mbcpersia\n#chandshanbeh\n#چندشنبه\n\nشبكه ام بى سى پرشيا را از حساب هاى مختلف در شبكه هاى اجتماعى دنبال كنيد\n►MBCPERSIA on Facebook:..."),
),
SearchVideo(
VideoItem(
id: "BeJqgI6rw9k",
title: "your city is full of fake buildings, here\'s why",
length: Some(725),
@ -129,7 +132,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCqVEHtQoXHmUCfJ-9smpTSg",
name: "Answer in Progress",
avatar: [
@ -139,17 +142,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 days ago"),
view_count: 1447008,
view_count: Some(1447008),
is_live: false,
is_short: false,
short_description: "Save 33% on your first Native Deodorant Pack - normally $39, youll get it for $26! Click here https://bit.ly/nativeanswer1 and use my code ANSWER #AD\n\nSomewhere on your street there may...",
is_upcoming: false,
short_description: Some("Save 33% on your first Native Deodorant Pack - normally $39, youll get it for $26! Click here https://bit.ly/nativeanswer1 and use my code ANSWER #AD\n\nSomewhere on your street there may..."),
),
SearchVideo(
VideoItem(
id: "ma28eWd1oyA",
title: "Post Malone, Maroon 5, Adele, Taylor Swift, Ed Sheeran, Shawn Mendes, Pop Hits 2020 Part 6",
length: Some(29989),
@ -160,7 +164,7 @@ Paginator(
height: 270,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCldQuUMYTUGrjvcU2vaPSFQ",
name: "Music Library",
avatar: [
@ -170,17 +174,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("Streamed 2 years ago"),
view_count: 1861814,
view_count: Some(1861814),
is_live: false,
is_short: false,
short_description: "Post Malone, Maroon 5, Adele, Taylor Swift, Ed Sheeran, Shawn Mendes, Charlie Puth Pop Hits 2020\nPost Malone, Maroon 5, Adele, Taylor Swift, Ed Sheeran, Shawn Mendes, Charlie Puth Pop Hits...",
is_upcoming: false,
short_description: Some("Post Malone, Maroon 5, Adele, Taylor Swift, Ed Sheeran, Shawn Mendes, Charlie Puth Pop Hits 2020\nPost Malone, Maroon 5, Adele, Taylor Swift, Ed Sheeran, Shawn Mendes, Charlie Puth Pop Hits..."),
),
SearchVideo(
VideoItem(
id: "mL2LBRM5GBI",
title: "Salahs 6-Minuten-Hattrick & Firmino-Gala: Rangers - FC Liverpool 1:7 | UEFA Champions League | DAZN",
length: Some(355),
@ -196,7 +201,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCB-GdMjyokO9lZkKU_oIK6g",
name: "DAZN UEFA Champions League",
avatar: [
@ -206,17 +211,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 days ago"),
view_count: 1471667,
view_count: Some(1471667),
is_live: false,
is_short: false,
short_description: "In der Liga läuft es für die Reds weiterhin nicht rund. Am vergangenen Spieltag gab es gegen Arsenal eine 2:3-Niederlage, am Sonntag trifft man auf Man City. Die Champions League soll für...",
is_upcoming: false,
short_description: Some("In der Liga läuft es für die Reds weiterhin nicht rund. Am vergangenen Spieltag gab es gegen Arsenal eine 2:3-Niederlage, am Sonntag trifft man auf Man City. Die Champions League soll für..."),
),
SearchVideo(
VideoItem(
id: "Ang18qz2IeQ",
title: "Satisfying Videos of Workers Doing Their Job Perfectly",
length: Some(1186),
@ -232,7 +238,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCYenDLnIHsoqQ6smwKXQ7Hg",
name: "#Mind Warehouse",
avatar: [
@ -242,17 +248,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 days ago"),
view_count: 173121,
view_count: Some(173121),
is_live: false,
is_short: false,
short_description: "TechZone ► https://goo.gl/Gj3wZs \n\n #incrediblemoments #mindwarehouse #IncredibleMoments #CaughtOnCamera #InterestingFacts \n\nYou can endlessly watch how others work, but in this selection,...",
is_upcoming: false,
short_description: Some("TechZone ► https://goo.gl/Gj3wZs \n\n #incrediblemoments #mindwarehouse #IncredibleMoments #CaughtOnCamera #InterestingFacts \n\nYou can endlessly watch how others work, but in this selection,..."),
),
SearchVideo(
VideoItem(
id: "fjHN4jsJnEU",
title: "I Made 200 Players Simulate Survival Island in Minecraft...",
length: Some(2361),
@ -268,7 +275,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCqt4mmAqLmH-AwXz31URJsw",
name: "Sword4000",
avatar: [
@ -278,17 +285,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 days ago"),
view_count: 751909,
view_count: Some(751909),
is_live: false,
is_short: false,
short_description: "200 Players Simulate Survival Island Civilizations in Minecraft...\n-------------------------------------------------------------------\nI invited 200 Players to a Survival Island and let them...",
is_upcoming: false,
short_description: Some("200 Players Simulate Survival Island Civilizations in Minecraft...\n-------------------------------------------------------------------\nI invited 200 Players to a Survival Island and let them..."),
),
SearchVideo(
VideoItem(
id: "FI1XrdBJIUI",
title: "Epic Construction Fails | Expensive Fails Compilation | FailArmy",
length: Some(631),
@ -304,7 +312,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCPDis9pjXuqyI7RYLJ-TTSA",
name: "FailArmy",
avatar: [
@ -314,17 +322,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 days ago"),
view_count: 2226471,
view_count: Some(2226471),
is_live: false,
is_short: false,
short_description: "I don\'t think so, Tim. ►►► Submit your videos for the chance to be featured 🔗 https://www.failarmy.com/pages/submit-video ▼ Follow us for more fails! https://linktr.ee/failarmy\n#fails...",
is_upcoming: false,
short_description: Some("I don\'t think so, Tim. ►►► Submit your videos for the chance to be featured 🔗 https://www.failarmy.com/pages/submit-video ▼ Follow us for more fails! https://linktr.ee/failarmy\n#fails..."),
),
SearchVideo(
VideoItem(
id: "MXdplejK8vU",
title: "Chilly autumn Jazz ☕ Smooth September Jazz & Bossa Nova for a great relaxing weekend",
length: Some(86403),
@ -340,7 +349,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCeGJ6v6KQt0s88hGKMfybuw",
name: "Cozy Jazz Music",
avatar: [
@ -350,17 +359,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 148743,
view_count: Some(148743),
is_live: false,
is_short: false,
short_description: "Chilly autumn Jazz ☕ Smooth September Jazz & Bossa Nova for a great relaxing weekend\nhttps://youtu.be/MXdplejK8vU\n*******************************************\nSounds available on: Jazz Bossa...",
is_upcoming: false,
short_description: Some("Chilly autumn Jazz ☕ Smooth September Jazz & Bossa Nova for a great relaxing weekend\nhttps://youtu.be/MXdplejK8vU\n*******************************************\nSounds available on: Jazz Bossa..."),
),
SearchVideo(
VideoItem(
id: "Jri4_9vBFiQ",
title: "Top 100 Best Classic Rock Songs Of All Time 🔥 R.E.M, Queen, Metallica,Guns N Roses,Bon Jovi, U2,CCR",
length: None,
@ -376,7 +386,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCiIWdzEVNH8okhlapR9a-xA",
name: "Rock Music",
avatar: [
@ -386,17 +396,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 192,
is_live: false,
view_count: Some(192),
is_live: true,
is_short: false,
short_description: "Top 100 Best Classic Rock Songs Of All Time 🔥 R.E.M, Queen, Metallica,Guns N Roses,Bon Jovi, U2,CCR\nTop 100 Best Classic Rock Songs Of All Time 🔥 R.E.M, Queen, Metallica,Guns N...",
is_upcoming: false,
short_description: Some("Top 100 Best Classic Rock Songs Of All Time 🔥 R.E.M, Queen, Metallica,Guns N Roses,Bon Jovi, U2,CCR\nTop 100 Best Classic Rock Songs Of All Time 🔥 R.E.M, Queen, Metallica,Guns N..."),
),
SearchVideo(
VideoItem(
id: "ll4d5Lt-Ie8",
title: "Relaxing Music Healing Stress, Anxiety and Depressive States Heal Mind, Body and Soul | Sleep music",
length: Some(42896),
@ -412,7 +423,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCNS3dqFGBPhxHmOigehpBeg",
name: "Love YourSelf",
avatar: [
@ -422,17 +433,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("Streamed 5 months ago"),
view_count: 5363904,
view_count: Some(5363904),
is_live: false,
is_short: false,
short_description: "The study found that listening to relaxing music of the patient\'s choice resulted in \"significant pain relief and increased mobility.\" Researchers believe that music relieves pain because listening...",
is_upcoming: false,
short_description: Some("The study found that listening to relaxing music of the patient\'s choice resulted in \"significant pain relief and increased mobility.\" Researchers believe that music relieves pain because listening..."),
),
SearchVideo(
VideoItem(
id: "Dx2wbKLokuQ",
title: "W. Putin: Die Sehnsucht nach dem Imperium | Mit offenen Karten | ARTE",
length: Some(729),
@ -448,7 +460,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCLLibJTCy3sXjHLVaDimnpQ",
name: "ARTEde",
avatar: [
@ -458,17 +470,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 539838,
view_count: Some(539838),
is_live: false,
is_short: false,
short_description: "Jede Woche untersucht „Mit offenen Karten“ die politischen Kräfteverhältnisse in der ganzen Welt anhand detaillierter geografischer Karten \n\nIm Februar 2022 rechtfertigte Wladimir Putin...",
is_upcoming: false,
short_description: Some("Jede Woche untersucht „Mit offenen Karten“ die politischen Kräfteverhältnisse in der ganzen Welt anhand detaillierter geografischer Karten \n\nIm Februar 2022 rechtfertigte Wladimir Putin..."),
),
SearchVideo(
VideoItem(
id: "jfKfPfyJRdk",
title: "lofi hip hop radio - beats to relax/study to",
length: None,
@ -484,7 +497,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCSJ4gkVC6NrvII8umztf0Ow",
name: "Lofi Girl",
avatar: [
@ -494,17 +507,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 21262,
is_live: false,
view_count: Some(21262),
is_live: true,
is_short: false,
short_description: "🤗 Thank you for listening, I hope you will have a good time here\n\n💽 | Get the latest vinyl (limited edition)\n→ https://vinyl-lofirecords.com/\n\n🎼 | Listen on Spotify, Apple music...",
is_upcoming: false,
short_description: Some("🤗 Thank you for listening, I hope you will have a good time here\n\n💽 | Get the latest vinyl (limited edition)\n→ https://vinyl-lofirecords.com/\n\n🎼 | Listen on Spotify, Apple music..."),
),
SearchVideo(
VideoItem(
id: "qmrzTUmZ4UU",
title: "850€ für den Verrat am System - UCS AT-AT LEGO® Star Wars 75313",
length: Some(2043),
@ -520,7 +534,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC_EZd3lsmxudu3IQzpTzOgw",
name: "Held der Steine Inh. Thomas Panke",
avatar: [
@ -530,17 +544,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 days ago"),
view_count: 600150,
view_count: Some(600150),
is_live: false,
is_short: false,
short_description: "Star Wars - erschienen 2021 - 6749 Teile\n\nDieses Set bei Amazon*:\nhttps://amzn.to/3yu9dHX\n\nErwähnt im Video*:\nTassen https://bit.ly/HdSBausteinecke\nBig Boy https://bit.ly/BBLokBigBoy\nBurg...",
is_upcoming: false,
short_description: Some("Star Wars - erschienen 2021 - 6749 Teile\n\nDieses Set bei Amazon*:\nhttps://amzn.to/3yu9dHX\n\nErwähnt im Video*:\nTassen https://bit.ly/HdSBausteinecke\nBig Boy https://bit.ly/BBLokBigBoy\nBurg..."),
),
SearchVideo(
VideoItem(
id: "t0Q2otsqC4I",
title: "Tom & Jerry | Tom & Jerry in Full Screen | Classic Cartoon Compilation | WB Kids",
length: Some(1298),
@ -556,7 +571,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC9trsD1jCTXXtN3xIOIU8gg",
name: "WB Kids",
avatar: [
@ -566,17 +581,18 @@ Paginator(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("10 months ago"),
view_count: 252381571,
view_count: Some(252381571),
is_live: false,
is_short: false,
short_description: "Did you know that there are only 25 classic Tom & Jerry episodes that were displayed in a widescreen CinemaScope from the 1950s? Enjoy a compilation filled with some of the best moments from...",
is_upcoming: false,
short_description: Some("Did you know that there are only 25 classic Tom & Jerry episodes that were displayed in a widescreen CinemaScope from the 1950s? Enjoy a compilation filled with some of the best moments from..."),
),
SearchVideo(
VideoItem(
id: "zE-a5eqvlv8",
title: "Dua Lipa, Coldplay, Martin Garrix & Kygo, The Chainsmokers Style - Feeling Me",
length: None,
@ -592,7 +608,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCX-USfenzQlhrEJR1zD5IYw",
name: "Deep Mood.",
avatar: [
@ -602,17 +618,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 955,
is_live: false,
view_count: Some(955),
is_live: true,
is_short: false,
short_description: "#Summermix #DeepHouse #DeepHouseSummerMix\nDua Lipa, Coldplay, Martin Garrix & Kygo, The Chainsmokers Style - Feeling Me\n\n🎵 All songs in this spotify playlist: https://spoti.fi/2TJ4Dyj\nSubmit...",
is_upcoming: false,
short_description: Some("#Summermix #DeepHouse #DeepHouseSummerMix\nDua Lipa, Coldplay, Martin Garrix & Kygo, The Chainsmokers Style - Feeling Me\n\n🎵 All songs in this spotify playlist: https://spoti.fi/2TJ4Dyj\nSubmit..."),
),
SearchVideo(
VideoItem(
id: "HxCcKzRAGWk",
title: "(Music for Man ) Relaxing Whiskey Blues Music - Modern Electric Guitar Blues - JAZZ & BLUES",
length: Some(42899),
@ -628,7 +645,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCGr-rTYtP1m-r_-ncspdVQQ",
name: "JAZZ & BLUES",
avatar: [
@ -638,17 +655,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("Streamed 3 months ago"),
view_count: 3156236,
view_count: Some(3156236),
is_live: false,
is_short: false,
short_description: "-----------------------------------------------------------------------------------\n✔Thanks for watching! Have a nice day!\n✔Don\'t forget LIKE - SHARE - COMMENT\n#bluesmusic#slowblues#bluesrock...",
is_upcoming: false,
short_description: Some("-----------------------------------------------------------------------------------\n✔Thanks for watching! Have a nice day!\n✔Don\'t forget LIKE - SHARE - COMMENT\n#bluesmusic#slowblues#bluesrock..."),
),
SearchVideo(
VideoItem(
id: "HlHYOdZePSE",
title: "Healing Music for Anxiety Disorders, Fears, Depression and Eliminate Negative Thoughts",
length: None,
@ -664,7 +682,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCqNYK5QArQRZSIR8v6_FCfA",
name: "Tranquil Music",
avatar: [
@ -674,17 +692,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 1585,
is_live: false,
view_count: Some(1585),
is_live: true,
is_short: false,
short_description: "Healing Music for Anxiety Disorders, Fears, Depression and Eliminate Negative Thoughts\n#HealingMusic #RelaxingMusic #TranquilMusic\n__________________________________\nMusic for:\nChakra healing....",
is_upcoming: false,
short_description: Some("Healing Music for Anxiety Disorders, Fears, Depression and Eliminate Negative Thoughts\n#HealingMusic #RelaxingMusic #TranquilMusic\n__________________________________\nMusic for:\nChakra healing...."),
),
SearchVideo(
VideoItem(
id: "CJ2AH3LJeic",
title: "Coldplay Greatest Hits Full Album 2022 New Songs of Coldplay 2022",
length: Some(7781),
@ -700,7 +719,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCdK2lzwelugXGhR9SCWuEew",
name: "PLAY MUSIC",
avatar: [
@ -710,17 +729,18 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 5595965,
view_count: Some(5595965),
is_live: false,
is_short: false,
short_description: "▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\nSubscribe channel for more videos:\n🔔Subscribe: https://bit.ly/2UbIZFv\n⚡Facebook: https://bitly.com.vn/gXDsC...",
is_upcoming: false,
short_description: Some("▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\nSubscribe channel for more videos:\n🔔Subscribe: https://bit.ly/2UbIZFv\n⚡Facebook: https://bitly.com.vn/gXDsC..."),
),
SearchVideo(
VideoItem(
id: "KJwzKxQ81iA",
title: "Handmade Candy Making Collection / 수제 사탕 만들기 모음 / Korean Candy Store",
length: Some(3152),
@ -736,7 +756,7 @@ Paginator(
height: 404,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCdGwDjTgbSwQDZ8dYOdrplg",
name: "Soon Films 순필름",
avatar: [
@ -746,17 +766,19 @@ Paginator(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 3127238,
view_count: Some(3127238),
is_live: false,
is_short: false,
short_description: "00:00 Handmade Candy Making\n13:43 Delicate Handmade Candy Making\n28:33 Rainbow Lollipop Handmade Candy Making\n39:10 Cute Handmade Candy Making",
is_upcoming: false,
short_description: Some("00:00 Handmade Candy Making\n13:43 Delicate Handmade Candy Making\n28:33 Rainbow Lollipop Handmade Candy Making\n39:10 Cute Handmade Candy Making"),
),
],
ctoken: Some("4qmFsgKbAxIPRkV3aGF0X3RvX3dhdGNoGuoCQ0JoNmlBSk5aMjlKYjB0NmVtOWlTR3hxVFRSdlYyMHdTMkYzYjFwbFdGSm1ZMGRHYmxwV09YcGliVVozWXpKb2RtUkdPWGxhVjJSd1lqSTFhR0pDU1daWFZFSXhUbFpuZDFSV09YSldNRlp0WkRCT1JWTlZPV3BsU0U1WFZHNWtiRXhWY0ZSa1ZrSlRXbmh2ZEVGQlFteGlaMEZDVmxaTlFVRlZVa1pCUVVWQlVtdFdNMkZIUmpCWU0xSjJXRE5rYUdSSFRtOUJRVVZCUVZGRlFVRkJSVUZCVVVGQlFWRkZRVmxyUlVsQlFrbFVZMGRHYmxwV09YcGliVVozWXpKb2RtUkdPVEJpTW5Sc1ltaHZWRU5MVDNJeFpuSjROR1p2UTBaU1YwSm1RVzlrVkZWSlN6RnBTVlJEUzA5eU1XWnllRFJtYjBOR1VsZENaa0Z2WkZSVlNVc3hkbkZqZURjd1NrRm5aMW8lM0SaAhpicm93c2UtZmVlZEZFd2hhdF90b193YXRjaA%3D%3D"),
visitor_data: Some("CgtjTXNGWnhNcjdORSiq8qmaBg%3D%3D"),
endpoint: browse,
)

View file

@ -34,7 +34,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -45,6 +45,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -75,7 +76,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -86,6 +87,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -117,7 +119,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -128,6 +130,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -162,7 +165,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -173,6 +176,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -203,7 +207,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -214,6 +218,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -244,7 +249,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -255,6 +260,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -285,7 +291,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -296,6 +302,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -326,7 +333,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -337,6 +344,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -367,7 +375,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -378,6 +386,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -408,7 +417,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -419,6 +428,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -449,7 +459,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -460,6 +470,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -490,7 +501,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -501,6 +512,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -531,7 +543,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -542,6 +554,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -572,7 +585,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -583,6 +596,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -613,7 +627,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -624,6 +638,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -654,7 +669,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -665,6 +680,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -695,7 +711,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -706,6 +722,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -736,7 +753,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -747,6 +764,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -754,4 +772,5 @@ Paginator(
),
],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyiwEKT0FEU0pfaTBhMTViQk5vTE9UTHFhUTBoZHB4VTN5SUdfYmhQTzhzM1pGQXQybzdnaVMwajVoSkRNSTl5MGs5M2l4SkM5VGdSbHBVa0xxQ0EiESILWmVlcnJudUxpNUUwAXgBKBIwAUIhZW5nYWdlbWVudC1wYW5lbC1jb21tZW50cy1zZWN0aW9u"),
endpoint: browse,
)

View file

@ -33,7 +33,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -44,6 +44,7 @@ Paginator(
count: Some(3),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyfhpLEhpVZ3djVTczT0JWOE9tU0JPS3J0NEFhQUJBZyICCAAqGFVDRWZfQmMtS1ZkN29uU2VpZlMzcHk5ZzILWmVlcnJudUxpNUVAAUgKQi9jb21tZW50LXJlcGxpZXMtaXRlbS1VZ3djVTczT0JWOE9tU0JPS3J0NEFhQUJBZw%3D%3D"),
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -74,7 +75,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -85,6 +86,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -115,7 +117,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -126,6 +128,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -156,7 +159,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -167,6 +170,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -197,7 +201,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -208,6 +212,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -243,7 +248,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -254,6 +259,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -290,7 +296,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -301,6 +307,7 @@ Paginator(
count: Some(2),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyfhpLEhpVZ3puZDRLcVU1azhBN2F4QjdWNEFhQUJBZyICCAAqGFVDRWZfQmMtS1ZkN29uU2VpZlMzcHk5ZzILWmVlcnJudUxpNUVAAUgKQi9jb21tZW50LXJlcGxpZXMtaXRlbS1VZ3puZDRLcVU1azhBN2F4QjdWNEFhQUJBZw%3D%3D"),
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -331,7 +338,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -342,6 +349,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -372,7 +380,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -383,6 +391,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -413,7 +422,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -424,6 +433,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -456,7 +466,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -467,6 +477,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -497,7 +508,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -508,6 +519,7 @@ Paginator(
count: Some(2),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyfhpLEhpVZ3lUbFpfa2tYNnJydDV3S0VwNEFhQUJBZyICCAAqGFVDRWZfQmMtS1ZkN29uU2VpZlMzcHk5ZzILWmVlcnJudUxpNUVAAUgKQi9jb21tZW50LXJlcGxpZXMtaXRlbS1VZ3lUbFpfa2tYNnJydDV3S0VwNEFhQUJBZw%3D%3D"),
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -538,7 +550,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -549,6 +561,7 @@ Paginator(
count: Some(2),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyfhpLEhpVZ3lnM0Q5ZFVJRXJKNHlfTDJsNEFhQUJBZyICCAAqGFVDRWZfQmMtS1ZkN29uU2VpZlMzcHk5ZzILWmVlcnJudUxpNUVAAUgKQi9jb21tZW50LXJlcGxpZXMtaXRlbS1VZ3lnM0Q5ZFVJRXJKNHlfTDJsNEFhQUJBZw%3D%3D"),
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -579,7 +592,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -590,6 +603,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -620,7 +634,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -631,6 +645,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -661,7 +676,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -672,6 +687,7 @@ Paginator(
count: Some(1),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyfhpLEhpVZ3hZcVlrRkFnV2IzSmFUSFl0NEFhQUJBZyICCAAqGFVDRWZfQmMtS1ZkN29uU2VpZlMzcHk5ZzILWmVlcnJudUxpNUVAAUgKQi9jb21tZW50LXJlcGxpZXMtaXRlbS1VZ3hZcVlrRkFnV2IzSmFUSFl0NEFhQUJBZw%3D%3D"),
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -702,7 +718,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -713,6 +729,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -743,7 +760,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -754,6 +771,7 @@ Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -784,7 +802,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -795,6 +813,7 @@ Paginator(
count: Some(4),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyfhpLEhpVZ3pvWmY5bkc3VkJOaGNETFJGNEFhQUJBZyICCAAqGFVDRWZfQmMtS1ZkN29uU2VpZlMzcHk5ZzILWmVlcnJudUxpNUVAAUgKQi9jb21tZW50LXJlcGxpZXMtaXRlbS1VZ3pvWmY5bkc3VkJOaGNETFJGNEFhQUJBZw%3D%3D"),
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -827,7 +846,7 @@ Paginator(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: None,
)),
publish_date: "[date]",
@ -838,6 +857,7 @@ Paginator(
count: Some(1),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyfhpLEhpVZ3lNZXExV0RoU1lBSUozSlFoNEFhQUJBZyICCAAqGFVDRWZfQmMtS1ZkN29uU2VpZlMzcHk5ZzILWmVlcnJudUxpNUVAAUgKQi9jb21tZW50LXJlcGxpZXMtaXRlbS1VZ3lNZXExV0RoU1lBSUozSlFoNEFhQUJBZw%3D%3D"),
endpoint: browse,
),
by_owner: false,
pinned: false,
@ -845,4 +865,5 @@ Paginator(
),
],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYy7QIKwwJnZXRfcmFua2VkX3N0cmVhbXMtLUNxY0JDSUFFRlJlMzBUZ2FuQUVLbHdFSTJGOFFnQVFZQnlLTUFidGhsd05sb1pHVEg0ZWRnUlVOc2dUX2pFRFYxOThSRmxGZFJTMVJiQ1hBUl9CTFNGREZKZ2FuS2FoMUVyeERGQU1xY1lnMThmSGdVSnBtZklqV2tER0FscUN1QzJLdU1FQjJYT25sVTZrd3ZBUjY5OHA2a2VGV3hLckxscGdtalZtelg4RHdPaDk1cGlMLVROOTl5YTZ1TDlpb0Y1LWc2Q3dqellGS1RPbnduRTF4V3lVSVdOUjlsRllZRUJRU0JRaUpJQmdBRWdVSWhpQVlBQklIQ0pjZ0VBOFlBUklGQ0lnZ0dBQVNCUWlISUJnQUVnY0loU0FRQnhnQkVnY0loQ0FRQkJnQkdBQSIRIgtaZWVycm51TGk1RTAAeAEoFEIQY29tbWVudHMtc2VjdGlvbg%3D%3D"),
endpoint: browse,
)

View file

@ -91,7 +91,7 @@ VideoDetails(
height: 176,
),
],
verification: verified,
verification: Verified,
subscriber_count: Some(30900000),
),
view_count: 233243423,
@ -104,7 +104,7 @@ VideoDetails(
recommended: Paginator(
count: None,
items: [
RecommendedVideo(
VideoItem(
id: "aRpkasmB6so",
title: "18 de setembro de 2022",
length: Some(184),
@ -120,7 +120,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCQYl87Oi9aWzz-CLhTw3Rzg",
name: "Allan Nascimento",
avatar: [
@ -130,16 +130,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 days ago"),
view_count: 996,
view_count: Some(996),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "lCXqNCd0m10",
title: "aespa(エスパ) Savage + Next Level + Black Mamba💕Stage Mix Compilation🔥에스파 무대모음 KBS Music Bank",
length: Some(898),
@ -155,7 +157,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCgqMjKxRWAKUvgYqgomighw",
name: "KBS충북",
avatar: [
@ -165,16 +167,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 months ago"),
view_count: 7684395,
view_count: Some(7684395),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "tDukIfFzX18",
title: "[MV] Hwa Sa(화사) _ Maria(마리아)",
length: Some(231),
@ -190,7 +194,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCweOkPb1wVVH0Q0Tlj4a5Pw",
name: "1theK (원더케이)",
avatar: [
@ -200,16 +204,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 260984648,
view_count: Some(260984648),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "e-ORhEE9VVg",
title: "Taylor Swift - Blank Space",
length: Some(273),
@ -225,7 +231,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCqECaJ8Gagnn7YCbPEzWH6g",
name: "Taylor Swift",
avatar: [
@ -235,16 +241,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 years ago"),
view_count: 3035220118,
view_count: Some(3035220118),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "qfVuRQX0ydQ",
title: "[MV] Weeekly(위클리) _ After School",
length: Some(225),
@ -260,7 +268,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCweOkPb1wVVH0Q0Tlj4a5Pw",
name: "1theK (원더케이)",
avatar: [
@ -270,16 +278,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 138451832,
view_count: Some(138451832),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "tyrVtwE8Gv0",
title: "NCT U 엔시티 유 \'Make A Wish (Birthday Song)\' MV",
length: Some(249),
@ -295,7 +305,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -305,16 +315,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 255458628,
view_count: Some(255458628),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "X-uJtV8ScYk",
title: "Stray Kids \"Back Door\" M/V",
length: Some(218),
@ -330,7 +342,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -340,16 +352,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 274719671,
view_count: Some(274719671),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "MjCZfZfucEc",
title: "ITZY “LOCO” M/V @ITZY",
length: Some(233),
@ -365,7 +379,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -375,16 +389,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 203129706,
view_count: Some(203129706),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "2FzSv66c7TQ",
title: "A E S P A (에스파) ALL SONGS PLAYLIST 2022 | 에스파 노래 모음",
length: Some(3441),
@ -400,7 +416,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCK8S6QMrTk1G8TYQwIyDo-w",
name: "LQ K-POP",
avatar: [
@ -410,16 +426,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 531757,
view_count: Some(531757),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CevxZvSJLk8",
title: "Katy Perry - Roar (Official)",
length: Some(270),
@ -435,7 +453,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCYvmuw-JtVrTZQ-7Y4kd63Q",
name: "Katy Perry",
avatar: [
@ -445,16 +463,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("9 years ago"),
view_count: 3656394146,
view_count: Some(3656394146),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "bwmSjveL3Lc",
title: "BLACKPINK - \'붐바야 (BOOMBAYAH)\' M/V",
length: Some(244),
@ -470,7 +490,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -480,16 +500,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 years ago"),
view_count: 1479871637,
view_count: Some(1479871637),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CM4CkVFmTds",
title: "TWICE \"I CAN\'T STOP ME\" M/V",
length: Some(221),
@ -505,7 +527,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -515,16 +537,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 456763969,
view_count: Some(456763969),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "ioNng23DkIM",
title: "BLACKPINK - \'How You Like That\' M/V",
length: Some(184),
@ -540,7 +564,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -550,16 +574,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 1149727787,
view_count: Some(1149727787),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "BL-aIpCLWnU",
title: "Black Mamba",
length: Some(175),
@ -575,7 +601,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa",
avatar: [
@ -585,16 +611,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 86080254,
view_count: Some(86080254),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Jh4QFaPmdss",
title: "(G)I-DLE - \'TOMBOY\' Official Music Video",
length: Some(198),
@ -610,7 +638,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCritGVo7pLJLUS8wEu32vow",
name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)",
avatar: [
@ -620,16 +648,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 169858302,
view_count: Some(169858302),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "WPdWvnAAurg",
title: "aespa 에스파 \'Savage\' MV",
length: Some(259),
@ -645,7 +675,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -655,16 +685,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 months ago"),
view_count: 216164610,
view_count: Some(216164610),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Z7yNvMzz2zg",
title: "Red Velvet 레드벨벳 \'Psycho\' Performance Video",
length: Some(216),
@ -680,7 +712,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCk9GmdlDTBfgGRb7vXeRMoQ",
name: "Red Velvet",
avatar: [
@ -690,26 +722,32 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 135093083,
view_count: Some(135093083),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("CBQSExILWmVlcnJudUxpNUXAAQHIAQEYACreBjJzNkw2d3pfQkFyOEJBb0Q4ajRBQ2czQ1Bnb0l5dFdIekt5Tm1ZMXBDZ1B5UGdBS0o5SS1KQW9pVUV4eU1UUldiR05sYkRKVE16UlpSMmw1WlZkRU1rOW9jbU4wVGt4Q1psVk9PUW9EOGo0QUNoTFNQZzhLRFZKRVdtVmxjbkp1ZFV4cE5VVUtBX0ktQUFvT3dqNExDTjIyMHJ2Q3h2cVNsQUVLQV9JLUFBb3cwajR0Q2l0U1JFTk1RVXMxZFhsZmF6STNkWFV0UlhSUlgySTFWVEp5TWpaRVRrUmFUMjFPY1Vka1kyTlZTVWRSQ2dQeVBnQUtEc0ktQ3dqZnZzMkxuNFRwbmJRQkNnUHlQZ0FLRGNJLUNnallxdldKeExEazhYc0tBX0ktQUFvT3dqNExDTlNUMDZfUXlOdjZxUUVLQV9JLUFBb093ajRMQ1AyMThJbnd0cldWdHdFS0FfSS1BQW9Od2o0S0NJbmp5ZmpWdHVMMVh3b0Q4ajRBQ2czQ1Bnb0l4LUM1djltdnBwZ3lDZ1B5UGdBS0RzSS1Dd2kwMnZQMC10ZTBydGdCQ2dQeVBnQUtEY0ktQ2dqUDNLU2s3Nno4OVFrS0FfSS1BQW9Od2o0S0NMZTVyN3p2MGVTRWJ3b0Q4ajRBQ2czQ1Bnb0kyNXVaaTVYU2dPY0lDZ1B5UGdBS0RzSS1Dd2lEb1k3dXR2RFp3WW9CQ2dQeVBnQUtEY0ktQ2dqMXRLMkVxY1RtM3dRS0FfSS1BQW9Od2o0S0NNdnRtWl9hZ29TUEpnb0Q4ajRBQ2czQ1Bnb0l1UFdDZ09mWDFmdFlDZ1B5UGdBS0RjSS1DZ2k0dHNfbnpMZWozbWNTRkFBQ0JBWUlDZ3dPRUJJVUZoZ2FIQjRnSWlRbUdnUUlBQkFCR2dRSUFoQURHZ1FJQkJBRkdnUUlCaEFIR2dRSUNCQUpHZ1FJQ2hBTEdnUUlEQkFOR2dRSURoQVBHZ1FJRUJBUkdnUUlFaEFUR2dRSUZCQVZHZ1FJRmhBWEdnUUlHQkFaR2dRSUdoQWJHZ1FJSEJBZEdnUUlIaEFmR2dRSUlCQWhHZ1FJSWhBakdnUUlKQkFsR2dRSUpoQW5LaFFBQWdRR0NBb01EaEFTRkJZWUdod2VJQ0lrSmdqD3dhdGNoLW5leHQtZmVlZA%3D%3D"),
visitor_data: Some("CgtCeURHR09uNlJ5TSjOiLqZBg%3D%3D"),
endpoint: next,
),
top_comments: Paginator(
count: Some(705000),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyJSIRIgtaZWVycm51TGk1RTAAeAJCEGNvbW1lbnRzLXNlY3Rpb24%3D"),
endpoint: next,
),
latest_comments: Paginator(
count: Some(705000),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyOCIRIgtaZWVycm51TGk1RTABeAIwAUIhZW5nYWdlbWVudC1wYW5lbC1jb21tZW50cy1zZWN0aW9u"),
endpoint: next,
),
)

View file

@ -91,7 +91,7 @@ VideoDetails(
height: 176,
),
],
verification: verified,
verification: Verified,
subscriber_count: Some(31000000),
),
view_count: 234258725,
@ -104,7 +104,7 @@ VideoDetails(
recommended: Paginator(
count: None,
items: [
RecommendedVideo(
VideoItem(
id: "WPdWvnAAurg",
title: "aespa 에스파 \'Savage\' MV",
length: Some(259),
@ -120,7 +120,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -130,16 +130,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 218055265,
view_count: Some(218055265),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "4TWR90KJl84",
title: "aespa 에스파 \'Next Level\' MV",
length: Some(236),
@ -155,7 +157,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -165,16 +167,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 248023999,
view_count: Some(248023999),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "uR8Mrt1IpXg",
title: "Red Velvet 레드벨벳 \'Psycho\' MV",
length: Some(216),
@ -190,7 +194,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -200,16 +204,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 347102621,
view_count: Some(347102621),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "UUUWIGx3hDE",
title: "ITZY \"WANNABE\" Performance Video",
length: Some(198),
@ -225,7 +231,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCDhM2k2Cua-JdobAh5moMFg",
name: "ITZY",
avatar: [
@ -235,16 +241,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 97453393,
view_count: Some(97453393),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "NoYKBAajoyo",
title: "EVERGLOW (에버글로우) - DUN DUN MV",
length: Some(209),
@ -260,7 +268,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC_pwIXKXNm5KGhdEVzmY60A",
name: "Stone Music Entertainment",
avatar: [
@ -270,16 +278,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 266364690,
view_count: Some(266364690),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "32si5cfrCNc",
title: "BLACKPINK - \'How You Like That\' DANCE PERFORMANCE VIDEO",
length: Some(181),
@ -295,7 +305,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -305,16 +315,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 1254749733,
view_count: Some(1254749733),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CM4CkVFmTds",
title: "TWICE \"I CAN\'T STOP ME\" M/V",
length: Some(221),
@ -330,7 +342,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -340,16 +352,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 459831562,
view_count: Some(459831562),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "UZPZyd5vE1c",
title: "Shut Down",
length: Some(176),
@ -365,7 +379,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -375,16 +389,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 7118730,
view_count: Some(7118730),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CKZvWhCqx1s",
title: "ROSÉ - \'On The Ground\' M/V",
length: Some(189),
@ -400,7 +416,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -410,16 +426,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 300492226,
view_count: Some(300492226),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "fE2h3lGlOsk",
title: "ITZY \"WANNABE\" M/V @ITZY",
length: Some(219),
@ -435,7 +453,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -445,16 +463,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 469178299,
view_count: Some(469178299),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Y8JFxS1HlDo",
title: "IVE 아이브 \'LOVE DIVE\' MV",
length: Some(179),
@ -470,7 +490,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCYDmx2Sfpnaxg488yBpZIGg",
name: "starshipTV",
avatar: [
@ -480,16 +500,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 161053206,
view_count: Some(161053206),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "dNCWe_6HAM8",
title: "LISA - \'MONEY\' EXCLUSIVE PERFORMANCE VIDEO",
length: Some(171),
@ -505,7 +527,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -515,16 +537,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 694135299,
view_count: Some(694135299),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "tyrVtwE8Gv0",
title: "NCT U 엔시티 유 \'Make A Wish (Birthday Song)\' MV",
length: Some(249),
@ -540,7 +564,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -550,16 +574,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 256797155,
view_count: Some(256797155),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "gU2HqP4NxUs",
title: "BLACKPINK - Pretty Savage 1011 SBS Inkigayo",
length: Some(208),
@ -575,7 +601,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -585,16 +611,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 285625201,
view_count: Some(285625201),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Ujb-gvqsoi0",
title: "Red Velvet - IRENE & SEULGI \'Monster\' MV",
length: Some(182),
@ -610,7 +638,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -620,16 +648,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 127297352,
view_count: Some(127297352),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "KhTeiaCezwM",
title: "[MV] MAMAMOO (마마무) - HIP",
length: Some(211),
@ -645,7 +675,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCuhAUMLzJxlP1W7mEk0_6lA",
name: "MAMAMOO",
avatar: [
@ -655,16 +685,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 357346135,
view_count: Some(357346135),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "XJDPzNzQ3RE",
title: "Run BTS! 2022 Special Episode - Fly BTS Fly Part 1",
length: Some(2070),
@ -680,7 +712,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCLkAepWjdylmXSltofFvsYQ",
name: "BANGTANTV",
avatar: [
@ -690,16 +722,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 hours ago"),
view_count: 748983,
view_count: Some(748983),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "0lXwMdnpoFQ",
title: "aespa 에스파 \'도깨비불 (Illusion)\' Dance Practice",
length: Some(210),
@ -715,7 +749,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC473RoZQE2gtgZJ61ZW0ZDQ",
name: "SMP FLOOR",
avatar: [
@ -725,16 +759,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 12347702,
view_count: Some(12347702),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "IHNzOHi8sJs",
title: "BLACKPINK - ‘뚜두뚜두 (DDU-DU DDU-DU) M/V",
length: Some(216),
@ -750,7 +786,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -760,26 +796,32 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 years ago"),
view_count: 1964840790,
view_count: Some(1964840790),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("CBQSExILWmVlcnJudUxpNUXAAQHIAQEYACqiDDJzNkw2d3lTQ1FxUENRb0Q4ajRBQ2czQ1Bnb0l1UFdDZ09mWDFmdFlDZ1B5UGdBS0RzSS1Dd2pPcjZhVTlMN2ttdUVCQ2dQeVBnQUtFdEktRHdvTlVrUmFaV1Z5Y201MVRHazFSUW9EOGo0QUNnN0NQZ3NJLU1xaTZ1MlZ3NC01QVFvRDhqNEFDZzNDUGdvSXNZamU0NGJFeGFKUkNnUHlQZ0FLRGNJLUNnaXF4bzYxd01DQ3d6WUtBX0ktQUFvT3dqNExDTmVSckxfYzNNaTEzd0VLQV9JLUFBb053ajRLQ051Ym1ZdVYwb0RuQ0FvRDhqNEFDZzNDUGdvSTE2YTg4NTI1OXNsUkNnUHlQZ0FLRGNJLUNnamJqcXVGb2V1YjB3Z0tBX0ktQUFvTndqNEtDTW4xbEkzbHUtaW1mQW9EOGo0QUNnM0NQZ29JdXFpZTZ0SzRrZUZqQ2dQeVBnQUtEY0ktQ2dqUGdaejB2OC1sNkhRS0FfSS1BQW9Pd2o0TENQMjE4SW53dHJXVnR3RUtBX0ktQUFvT3dqNExDTXVLdF9DUDllR21nUUVLQV9JLUFBb053ajRLQ0szRXN0V3YwTC1iVWdvRDhqNEFDZzNDUGdvSWc1NzdoSnJSdDRvcUNnUHlQZ0FLRGNJLUNnaVJ1c1BtemZtenlGd0tBX0ktQUFvT3dqNExDTlRBcHMtZGh2eXEwZ0VLQV9JLUFBb053ajRLQ0p2aDhzV0g1OXk1SUFvRDhqNEFDaF9TUGh3S0dsSkVRVTk2ZFZaM1JWbDNZMUZFTkhWMmNHZEJUbU5JU0ZWM0NoX1NQaHdLR2xKRVFVOWZjQzFWYmpCSGVUbHVXRlZ0Wm1kaE0xTlNYMXAzQ2hfU1Bod0tHbEpFUVU5cFEwaENhR3R1VTBSd09HcFZWekJPUzFoWU9FMVJDaF9TUGh3S0dsSkVRVTlYWjBsd1lVbDZha1p6UVhkeE5GOXhWR2hyTlROQkNoX1NQaHdLR2xKRVFVOXFNVkpuZEhkZmVtZHJibWxSWkdkTU5XTnlVRmxCQ2hfU1Bod0tHbEpFUVU4NWExbHRhMU5KVG5CVGFYVldTalEzUjNkT1RWSm5DaF9TUGh3S0dsSkVRVTlGYjNOTlVtbHlhM1ZKTjNvNE1tSmZia0oyUjNoQkNoX1NQaHdLR2xKRVFVOW1PRlExTURaUVZGcFVWRmxDWm01RVRVNURiR0ZSQ2hfU1Bod0tHbEpFUVU5UllqSlhRWGxLYTBwMlRURmhaMGRYZEhkRkxVOUJDaF9TUGh3S0dsSkVRVTlNWDFGNk1scFJRbUZNUkROTFExTnFWalpYZG5wM0NoX1NQaHdLR2xKRVFVOXpjeTFGWVdSRFpHZzBUVmxYV0hsMGFtWkpabFYzQ2hfU1Bod0tHbEpFUVU4MVRraFVXblJGV0ROSGJIWlhRMjgyYTJOdGFrdDNDaF9TUGh3S0dsSkVRVTlMWDBjMVRVZzFaM0ZJUTNRd1VXdENZVlZJTjJwUkNoX1NQaHdLR2xKRVFVOVpUWEZhWlV4U1RXMXhaRW8zZGs5b09UQXRhME5CQ2hfU1Bod0tHbEpFUVU4eVNGbEJhMFpIYzBGSmFWVmthRE5NVUhGRE5UZG5FaFVBQWdRR0NBb01EaEFTRkJZWUdod2VJQ0lrSmlnYUJBZ0FFQUVhQkFnQ0VBTWFCQWdFRUFVYUJBZ0dFQWNhQkFnSUVBa2FCQWdLRUFzYUJBZ01FQTBhQkFnT0VBOGFCQWdRRUJFYUJBZ1NFQk1hQkFnVUVCVWFCQWdXRUJjYUJBZ1lFQmthQkFnYUVCc2FCQWdjRUIwYUJBZ2VFQjhhQkFnZ0VDRWFCQWdpRUNNYUJBZ2tFQ1VhQkFnbUVDY2FCQWdvRUNrYUJBZ29FQ29hQkFnb0VDc2FCQWdvRUN3YUJBZ29FQzBhQkFnb0VDNGFCQWdvRUM4YUJBZ29FREFhQkFnb0VERWFCQWdvRURJYUJBZ29FRE1hQkFnb0VEUWFCQWdvRURVYUJBZ29FRFlhQkFnb0VEY3FGUUFDQkFZSUNnd09FQklVRmhnYUhCNGdJaVFtS0FqD3dhdGNoLW5leHQtZmVlZA%3D%3D"),
visitor_data: Some("Cgs2V0p6ZW5ab1ozTSjkrpaaBg%3D%3D"),
endpoint: next,
),
top_comments: Paginator(
count: Some(705000),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyJSIRIgtaZWVycm51TGk1RTAAeAJCEGNvbW1lbnRzLXNlY3Rpb24%3D"),
endpoint: next,
),
latest_comments: Paginator(
count: Some(705000),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyOCIRIgtaZWVycm51TGk1RTABeAIwAUIhZW5nYWdlbWVudC1wYW5lbC1jb21tZW50cy1zZWN0aW9u"),
endpoint: next,
),
)

View file

@ -287,7 +287,7 @@ VideoDetails(
height: 176,
),
],
verification: verified,
verification: Verified,
subscriber_count: Some(14900000),
),
view_count: 1251797,
@ -525,7 +525,7 @@ VideoDetails(
recommended: Paginator(
count: None,
items: [
RecommendedVideo(
VideoItem(
id: "t03rmc-prJo",
title: "This PC took 600 HOURS to Build!",
length: Some(1505),
@ -541,7 +541,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -551,16 +551,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 3449572,
view_count: Some(3449572),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "4ozYlgOuYis",
title: "They told me I was stupid - heating my pool with computers",
length: Some(691),
@ -576,7 +578,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -586,16 +588,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 3209930,
view_count: Some(3209930),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "THxkY59_xko",
title: "Is the fastest GPU ALWAYS the best?",
length: Some(979),
@ -611,7 +615,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -621,16 +625,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 hours ago"),
view_count: 640179,
view_count: Some(640179),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "UJ-KZzVUV7U",
title: "This toaster cost HOW MUCH?? - Revolution InstaGLO R270 Toaster",
length: Some(880),
@ -646,7 +652,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCdBK94H6oZT2Q7l0-b0xmMg",
name: "ShortCircuit",
avatar: [
@ -656,16 +662,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 905709,
view_count: Some(905709),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "yayAQAC1XiE",
title: "Intel PLEASE let me Overclock this!",
length: Some(799),
@ -681,7 +689,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -691,16 +699,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 days ago"),
view_count: 998245,
view_count: Some(998245),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "y4T374GtKLI",
title: "When The Grid Goes Down: How To Power Essential Devices (i.e., Refrigerator)",
length: Some(1239),
@ -716,7 +726,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCmb2QRAjdnkse21CtxAQ-cA",
name: "City Prepping",
avatar: [
@ -726,16 +736,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 132460,
view_count: Some(132460),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "b3x28s61q3c",
title: "The most EXPENSIVE thing I own.",
length: Some(887),
@ -751,7 +763,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -761,16 +773,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 2372992,
view_count: Some(2372992),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "LQ95XJAwaoc",
title: "My favorite car (sucks) - Lucid Air GT",
length: Some(1162),
@ -786,7 +800,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCdBK94H6oZT2Q7l0-b0xmMg",
name: "ShortCircuit",
avatar: [
@ -796,16 +810,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 565416,
view_count: Some(565416),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "WVjtK71qqXU",
title: "I bought a SECOND GPU… but NOT for gaming…",
length: Some(754),
@ -821,7 +837,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -831,16 +847,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 day ago"),
view_count: 1199845,
view_count: Some(1199845),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "vtvFVH9JdNI",
title: "I bought every Nintendo Console EVER.",
length: Some(1381),
@ -856,7 +874,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCMiJRAwDNSNzuYeN2uWa0pA",
name: "Mrwhosetheboss",
avatar: [
@ -866,16 +884,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 days ago"),
view_count: 1379793,
view_count: Some(1379793),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "J6Ga4wciA2k",
title: "THIS Wish.com Gaming PC is WORSE!",
length: Some(1545),
@ -891,7 +911,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -901,16 +921,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 2775764,
view_count: Some(2775764),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CsoKWsZ-Tyw",
title: "The Personal Gaming Theater - HOLY $H!T Samsung Odyssey Ark",
length: Some(1182),
@ -926,7 +948,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -936,16 +958,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 2449262,
view_count: Some(2449262),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "9T98VsMe3oo",
title: "How are we going to do this?",
length: Some(1124),
@ -961,7 +985,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -971,16 +995,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 4321218,
view_count: Some(4321218),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "5Hxr9k5Vdc4",
title: "Building the $1,000,000 Computer",
length: Some(1659),
@ -996,7 +1022,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -1006,16 +1032,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 3270062,
view_count: Some(3270062),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "12Hcbx33Rb4",
title: "BREAKING NEWS! - EVGA will no longer do business with NVIDIA",
length: Some(1262),
@ -1031,7 +1059,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCkWQ0gDrqOCarmUKmppD7GQ",
name: "JayzTwoCents",
avatar: [
@ -1041,16 +1069,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 1274410,
view_count: Some(1274410),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "EHkkwCjQzsc",
title: "Prepper (2016) | Full Post-Apocalyptic Thriller Movie HD",
length: Some(5982),
@ -1066,7 +1096,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCRX7UEyE8kp35mPrgC2sosA",
name: "JoBlo Movies",
avatar: [
@ -1076,16 +1106,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 209854,
view_count: Some(209854),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "AOdp09SYhCc",
title: "This Is So Embarrassing! - Building a PC with My Sister",
length: Some(1063),
@ -1101,7 +1133,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -1111,16 +1143,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 2453269,
view_count: Some(2453269),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CTIpNtHWVtQ",
title: "Why Pay $1000 for a 25 year old PC! - NIXSYS Windows 98 PC",
length: Some(1112),
@ -1136,7 +1170,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -1146,16 +1180,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 1478434,
view_count: Some(1478434),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "3RIp7CwkBeA",
title: "I Hope You Have a LOT of Money... RTX 4000 Announced",
length: Some(569),
@ -1171,7 +1207,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -1181,16 +1217,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 1816036,
view_count: Some(1816036),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "HZiaHEmE9PQ",
title: "Buying a Chromebook was a BIG MISTAKE",
length: Some(880),
@ -1206,7 +1244,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -1216,26 +1254,32 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("9 days ago"),
view_count: 1625226,
view_count: Some(1625226),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("CBQSExILbkZEQnhCVWZFNzTAAQHIAQEYACqIBjJzNkw2d3lfQkFxOEJBb0Q4ajRBQ2c3Q1Bnc0ltdG1tX1p6ei1xYTNBUW9EOGo0QUNnN0NQZ3NJcThTNW5lQ1N0c2JpQVFvRDhqNEFDZzNDUGdvSXlvel8tN21NbWI1TUNnUHlQZ0FLRGNJLUNnaTFyOUdxODh6aXoxQUtBX0ktQUFvT3dqNExDS0c4MVlXQWlLRFd5UUVLQV9JLUFBb093ajRMQ0xMUnRJMzRfYjNDeXdFS0FfSS1BQW9Od2o0S0NQZlcxdldzM3AyLWJ3b0Q4ajRBQ2czQ1Bnb0loOVhCZ2NtcjNvY3RDZ1B5UGdBS0RjSS1DZ2oxMHFycnU2VzdyRmtLQV9JLUFBb093ajRMQ05McHBmckhxdkh0dmdFS0FfSS1BQW9Od2o0S0NPbUdpTG13M09iUUp3b0Q4ajRBQ2czQ1Bnb0lySjc1czZ6TGd1VUtDZ1B5UGdBS0RzSS1Dd2lLdmZ1WTdJcmZuX1VCQ2dQeVBnQUtEc0ktQ3dqTzY5WHk1UDZhdnVRQkNnUHlQZ0FLRHNJLUN3aS1pOTN2OFkzM3NOY0JDZ1B5UGdBS0RjSS1DZ2pIbmNQR2dwakp2QkFLQV9JLUFBb013ajRKQ0tlSTRxUzl1dHB6Q2dQeVBnQUtEY0ktQ2dqVXJkbU83YWFLbVFrS0FfSS1BQW9Pd2o0TENPQ0xrT0hDdllxSjNRRUtBX0ktQUFvTndqNEtDUFRwazh6RXc2Yk1IUklVQUFJRUJnZ0tEQTRRRWhRV0dCb2NIaUFpSkNZYUJBZ0FFQUVhQkFnQ0VBTWFCQWdFRUFVYUJBZ0dFQWNhQkFnSUVBa2FCQWdLRUFzYUJBZ01FQTBhQkFnT0VBOGFCQWdRRUJFYUJBZ1NFQk1hQkFnVUVCVWFCQWdXRUJjYUJBZ1lFQmthQkFnYUVCc2FCQWdjRUIwYUJBZ2VFQjhhQkFnZ0VDRWFCQWdpRUNNYUJBZ2tFQ1VhQkFnbUVDY3FGQUFDQkFZSUNnd09FQklVRmhnYUhCNGdJaVFtag93YXRjaC1uZXh0LWZlZWQ%3D"),
visitor_data: Some("Cgtidzg4MlRTb3FKSSiqipeaBg%3D%3D"),
endpoint: next,
),
top_comments: Paginator(
count: Some(3200),
items: [],
ctoken: Some("Eg0SC25GREJ4QlVmRTc0GAYyJSIRIgtuRkRCeEJVZkU3NDAAeAJCEGNvbW1lbnRzLXNlY3Rpb24%3D"),
endpoint: next,
),
latest_comments: Paginator(
count: Some(3200),
items: [],
ctoken: Some("Eg0SC25GREJ4QlVmRTc0GAYyOCIRIgtuRkRCeEJVZkU3NDABeAIwAUIhZW5nYWdlbWVudC1wYW5lbC1jb21tZW50cy1zZWN0aW9u"),
endpoint: next,
),
)

View file

@ -26,7 +26,7 @@ VideoDetails(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: Some(1480),
),
view_count: 205,
@ -40,15 +40,18 @@ VideoDetails(
count: Some(0),
items: [],
ctoken: None,
endpoint: browse,
),
top_comments: Paginator(
count: None,
items: [],
ctoken: Some("Eg0SC0hSS3UwY3Zycl9vGAYyJSIRIgtIUkt1MGN2cnJfbzABeAJCEGNvbW1lbnRzLXNlY3Rpb24%3D"),
endpoint: next,
),
latest_comments: Paginator(
count: None,
items: [],
ctoken: Some("Eg0SC0hSS3UwY3Zycl9vGAYyOCIRIgtIUkt1MGN2cnJfbzABeAIwAUIhZW5nYWdlbWVudC1wYW5lbC1jb21tZW50cy1zZWN0aW9u"),
endpoint: next,
),
)

View file

@ -38,7 +38,7 @@ VideoDetails(
height: 176,
),
],
verification: none,
verification: None,
subscriber_count: Some(172000),
),
view_count: 2493983,
@ -51,7 +51,7 @@ VideoDetails(
recommended: Paginator(
count: None,
items: [
RecommendedVideo(
VideoItem(
id: "-YpwsdRKt8Q",
title: "SpiegelMining Reverse Engineering von Spiegel-Online (33c3)",
length: Some(3526),
@ -67,7 +67,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -77,16 +77,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 years ago"),
view_count: 2749364,
view_count: Some(2749364),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "4z3mu63yxII",
title: "Gregor Gysi & Martin Sonneborn",
length: Some(5272),
@ -102,7 +104,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCBWSgdr27NcLig0XzWLq2gQ",
name: "MISS-VERSTEHEN SIE MICH RICHTIG",
avatar: [
@ -112,16 +114,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 2266658,
view_count: Some(2266658),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "WhgRRpA3b2c",
title: "36C3 - Verkehrswende selber hacken",
length: Some(3176),
@ -137,7 +141,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -147,16 +151,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 260941,
view_count: Some(260941),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "5qNHtdN07FM",
title: "GPN16: Wie baut man eigentlich Raumschiffe (urs)",
length: Some(5172),
@ -172,7 +178,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -182,16 +188,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 years ago"),
view_count: 1229987,
view_count: Some(1229987),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "7FeqF1-Z1g0",
title: "David Kriesel: Traue keinem Scan, den du nicht selbst gefälscht hast",
length: Some(3820),
@ -207,7 +215,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -217,16 +225,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 years ago"),
view_count: 6095028,
view_count: Some(6095028),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "1vcP9UWrWBI",
title: "Easterhegg 2019 - Kernreaktoren",
length: Some(7263),
@ -242,7 +252,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -252,16 +262,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 46470,
view_count: Some(46470),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "jnp1veXQf7U",
title: "Blockchain - Ein außer Kontrolle geratenes Laborexperiment? #GPN19",
length: Some(3362),
@ -277,7 +289,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -287,16 +299,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 25136,
view_count: Some(25136),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "77OlKRkaixo",
title: "leyrer, MacLemon: E-Mail. Hässlich, aber es funktioniert #eh16",
length: Some(6998),
@ -312,7 +326,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -322,16 +336,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 years ago"),
view_count: 44410,
view_count: Some(44410),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "u29--YNGMyg",
title: "Physikalisches Kolloquium 22. Juli 2011 - Vortrag von Prof. Dr. Harald Lesch",
length: Some(6715),
@ -347,7 +363,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCvZLsBb-8Og4FvBUom9zPHQ",
name: "Universität Bayreuth",
avatar: [
@ -357,16 +373,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 years ago"),
view_count: 4184357,
view_count: Some(4184357),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "urt2_ACal9A",
title: "CCC-Jahresrückblick 2016 (33c3)",
length: Some(8170),
@ -382,7 +400,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -392,16 +410,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 years ago"),
view_count: 36111,
view_count: Some(36111),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "PnBs9oH2Lx8",
title: "Easterhegg 2019 - Wie ich die Regierung gehackt habe",
length: Some(3147),
@ -417,7 +437,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -427,16 +447,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 20322,
view_count: Some(20322),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "yaCiVvBD-xc",
title: "Mathias Dalheimer: Wie man einen Blackout verursacht",
length: Some(3748),
@ -452,7 +474,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -462,16 +484,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 years ago"),
view_count: 482258,
view_count: Some(482258),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "1PJnEwoFSXo",
title: "Das Geheimnis der Hieroglyphen | Doku HD | ARTE",
length: Some(5541),
@ -487,7 +511,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCLLibJTCy3sXjHLVaDimnpQ",
name: "ARTEde",
avatar: [
@ -497,16 +521,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("12 days ago"),
view_count: 427756,
view_count: Some(427756),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "iIDZ8pJKLZA",
title: "36C3 ChaosWest: Bahn API Chaos",
length: Some(3056),
@ -522,7 +548,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -532,16 +558,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 26926,
view_count: Some(26926),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "PhUQN6fd5O4",
title: "35C3 - Jahresrückblick des CCC 2018",
length: Some(8102),
@ -557,7 +585,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -567,16 +595,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 126093,
view_count: Some(126093),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "bzr0c8qzQoc",
title: "GPN19 - Beton",
length: Some(3972),
@ -592,7 +622,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -602,16 +632,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 13243,
view_count: Some(13243),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "IeX1F-Jjq9E",
title: "Lars “Pylon” Weiler (DC4LW): Weltraumkommunikation",
length: Some(5075),
@ -627,7 +659,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -637,16 +669,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 years ago"),
view_count: 80624,
view_count: Some(80624),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "gsnL4m57MCM",
title: "David Kriesel: SpiegelMining Reverse Engineering von Spiegel-Online",
length: Some(3526),
@ -662,7 +696,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCeO-zvUfuEdPMDoNST6hy1A",
name: "Killuminati ∆",
avatar: [
@ -672,16 +706,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 years ago"),
view_count: 29009,
view_count: Some(29009),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "uEEHq6f8RsM",
title: "Leyrer: Moderne Linux Kommandozeilenwerkzeuge - Edition \"Allein zu Haus\"",
length: Some(3716),
@ -697,7 +733,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de",
avatar: [
@ -707,26 +743,32 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 months ago"),
view_count: 67538,
view_count: Some(67538),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("CBQSExILMHJiOUNmT3ZvamvAAQHIAQEYACqrBjJzNkw2d3paQkFyV0JBb0Q4ajRBQ2c3Q1Bnc0l4Ty1xb3AyV25NWDVBUW9EOGo0QUNnN0NQZ3NJZ29uTDc3clgtWjdqQVFvRDhqNEFDZzNDUGdvSTU5N2RnZW1vaEl4YUNnUHlQZ0FLSWRJLUhnb2NVa1JEVFZWRE1sUlljVjkwTURaSWFtUnlNbWRmUzJSTGNFaFJad29EOGo0QUNnN0NQZ3NJMDlqVG05MzIwZEhtQVFvRDhqNEFDZzdDUGdzSWphem5fUFhDNnF2c0FRb0Q4ajRBQ2c3Q1Bnc0lrckN0cmRULXdfdldBUW9EOGo0QUNnN0NQZ3NJdGZfQnJ0NjNuYjJPQVFvRDhqNEFDZzdDUGdzSW1wYnF5SkdsNmRudkFRb0Q4ajRBQ2c3Q1Bnc0lxT2FZbXBqZjM3ZTdBUW9EOGo0QUNnN0NQZ3NJMEtfcWhNRGYzZDI2QVFvRDhqNEFDZzNDUGdvSW45N1lqLWllbTdnLUNnUHlQZ0FLRHNJLUN3aVg5by1DNzhxbzBNa0JDZ1B5UGdBS0RzSS1Dd2o2a3BYUXNPS1otZFFCQ2dQeVBnQUtEc0ktQ3dpUTI2aVNxYjYyd0lnQkNnUHlQZ0FLRGNJLUNnanV5ZmUtLW9iRWlqNEtBX0ktQUFvTndqNEtDSWVGemRXOGpyMmRid29EOGo0QUNnM0NQZ29JMGRlT2tfNmlfZkloQ2dQeVBnQUtEc0ktQ3dpajRPenpwdnp5NUlJQkNnUHlQZ0FLRHNJLUN3akRqZkdfdXZYQm9MZ0JFaFFBQWdRR0NBb01EaEFTRkJZWUdod2VJQ0lrSmhvRUNBQVFBUm9FQ0FJUUF4b0VDQVFRQlJvRUNBWVFCeG9FQ0FnUUNSb0VDQW9RQ3hvRUNBd1FEUm9FQ0E0UUR4b0VDQkFRRVJvRUNCSVFFeG9FQ0JRUUZSb0VDQllRRnhvRUNCZ1FHUm9FQ0JvUUd4b0VDQndRSFJvRUNCNFFIeG9FQ0NBUUlSb0VDQ0lRSXhvRUNDUVFKUm9FQ0NZUUp5b1VBQUlFQmdnS0RBNFFFaFFXR0JvY0hpQWlKQ1lqD3dhdGNoLW5leHQtZmVlZA%3D%3D"),
visitor_data: Some("CgtoY1pQUF8wNW1qayjSjpSZBg%3D%3D"),
endpoint: next,
),
top_comments: Paginator(
count: Some(2200),
items: [],
ctoken: Some("Eg0SCzByYjlDZk92b2prGAYyJSIRIgswcmI5Q2ZPdm9qazAAeAJCEGNvbW1lbnRzLXNlY3Rpb24%3D"),
endpoint: next,
),
latest_comments: Paginator(
count: Some(2200),
items: [],
ctoken: Some("Eg0SCzByYjlDZk92b2prGAYyOCIRIgswcmI5Q2ZPdm9qazABeAIwAUIhZW5nYWdlbWVudC1wYW5lbC1jb21tZW50cy1zZWN0aW9u"),
endpoint: next,
),
)

View file

@ -281,7 +281,7 @@ VideoDetails(
height: 176,
),
],
verification: verified,
verification: Verified,
subscriber_count: Some(14800000),
),
view_count: 971966,
@ -519,7 +519,7 @@ VideoDetails(
recommended: Paginator(
count: None,
items: [
RecommendedVideo(
VideoItem(
id: "AOdp09SYhCc",
title: "This Is So Embarrassing!",
length: Some(1063),
@ -535,7 +535,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -545,16 +545,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 days ago"),
view_count: 1862544,
view_count: Some(1862544),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CY3OQh-7wIk",
title: "The Computer I Would Actually BUY",
length: Some(6478),
@ -570,7 +572,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -580,16 +582,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("Streamed 8 days ago"),
view_count: 946996,
view_count: Some(946996),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "LQ95XJAwaoc",
title: "My favorite car (sucks)",
length: Some(1162),
@ -605,7 +609,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCdBK94H6oZT2Q7l0-b0xmMg",
name: "ShortCircuit",
avatar: [
@ -615,16 +619,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 day ago"),
view_count: 349251,
view_count: Some(349251),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "mhMQeJ5Qmp0",
title: "The Apple Newton MessagePad.",
length: Some(758),
@ -640,7 +646,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC7Jwj9fkrf1adN4fMmTkpug",
name: "DankPods",
avatar: [
@ -650,16 +656,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 day ago"),
view_count: 375458,
view_count: Some(375458),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "1ctXiZsN6ac",
title: "The Reviewer Got Reviewed - WAN Show September 9, 2022",
length: Some(10265),
@ -675,7 +683,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -685,16 +693,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("Streamed 6 days ago"),
view_count: 734463,
view_count: Some(734463),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CMR9z9Xr8GM",
title: "Storing Solar Power on my ROOF!!!",
length: Some(1028),
@ -710,7 +720,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCKd49wwdEdIoM-7Fumhwmog",
name: "Quint BUILDs",
avatar: [
@ -720,16 +730,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 months ago"),
view_count: 2773698,
view_count: Some(2773698),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "fT2KhJ8W-Kg",
title: "How gas pumps know when to turn themselves off",
length: Some(836),
@ -745,7 +757,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEIwxahdLz7bap-VDs9h35A",
name: "Steve Mould",
avatar: [
@ -755,16 +767,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 hours ago"),
view_count: 219605,
view_count: Some(219605),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "12Hcbx33Rb4",
title: "BREAKING NEWS! - EVGA will no longer do business with NVIDIA",
length: Some(1262),
@ -780,7 +794,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCkWQ0gDrqOCarmUKmppD7GQ",
name: "JayzTwoCents",
avatar: [
@ -790,16 +804,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 hours ago"),
view_count: 145345,
view_count: Some(145345),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "QW1SsqmaIuE",
title: "I Surprised My Subscriber with his Dream Gaming Setup! - Season 8",
length: Some(2177),
@ -815,7 +831,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UChIZGfcnjHI0DG4nweWEduw",
name: "TechSource",
avatar: [
@ -825,16 +841,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 hours ago"),
view_count: 50033,
view_count: Some(50033),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "JAcSNL1T3OA",
title: "Why Did I Drill 1756 Holes in This?",
length: Some(1293),
@ -850,7 +868,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVveEFTOd6khhSXXnRhxJmg",
name: "Fireball Tool",
avatar: [
@ -860,16 +878,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: 1163652,
view_count: Some(1163652),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "ZVtOss1U7_s",
title: "VW Beetle converted to electric in a day",
length: Some(826),
@ -885,7 +905,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCq1Oqk1I7zeYlDiJTFWLoFA",
name: "Electric Classic Cars",
avatar: [
@ -895,16 +915,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 3266169,
view_count: Some(3266169),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "2kJDTzFtUr4",
title: "How ASML, TSMC And Intel Dominate The Chip Market | CNBC Marathon",
length: Some(3399),
@ -920,7 +942,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCvJJ_dzjViJCoLf5uKUTwoA",
name: "CNBC",
avatar: [
@ -930,16 +952,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 678935,
view_count: Some(678935),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "0rCbfsuKdYw",
title: "I bought every Playstation Ever.",
length: Some(1046),
@ -955,7 +979,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCMiJRAwDNSNzuYeN2uWa0pA",
name: "Mrwhosetheboss",
avatar: [
@ -965,16 +989,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 7569956,
view_count: Some(7569956),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "sbdU7AkH6QM",
title: "Reviewing Free Energy Generators. A Response to My Video \"Nikola Tesla\'s Greatest Invention\"- 102",
length: Some(1387),
@ -990,7 +1016,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC_SLthyNX_ivd-dmsFgmJVg",
name: "Jeremy Fielding",
avatar: [
@ -1000,16 +1026,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 months ago"),
view_count: 3374461,
view_count: Some(3374461),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "zcchDu7KoYs",
title: "AMDs Victory Lap - HOLY $H!T Threadripper Pro 5995WX",
length: Some(872),
@ -1025,7 +1053,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -1035,16 +1063,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 days ago"),
view_count: 1322625,
view_count: Some(1322625),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "pd6DsSjqhFE",
title: "Top Gear Satisfaction Survey Compilation",
length: Some(986),
@ -1060,7 +1090,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCupQghOyPai8Hxg4RqMERvA",
name: "incT",
avatar: [
@ -1070,16 +1100,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 255945,
view_count: Some(255945),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "2K5Gqp1cEcM",
title: "Why our Screwdriver took 3 YEARS",
length: Some(1752),
@ -1095,7 +1127,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -1105,16 +1137,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: 2930532,
view_count: Some(2930532),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "t03rmc-prJo",
title: "This PC took 600 HOURS to Build!",
length: Some(1505),
@ -1130,7 +1164,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips",
avatar: [
@ -1140,16 +1174,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("12 days ago"),
view_count: 2743664,
view_count: Some(2743664),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "QTH9m6MDIfc",
title: "One Year Ago I Built an Ecosystem, This Happened",
length: Some(485),
@ -1165,7 +1201,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCYmna5rFHIesFteksAvFOfg",
name: "Dr. Plants",
avatar: [
@ -1175,26 +1211,32 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: 7958495,
view_count: Some(7958495),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("CBQSExILbkZEQnhCVWZFNzTAAQHIAQEYACqkBjJzNkw2d3pVQkFyUkJBb0Q4ajRBQ2d6Q1Bna0lwNGppcEwyNjJuTUtBX0ktQUFvTndqNEtDSW1CN18yaHlQUEdDUW9EOGo0QUNnM0NQZ29JaDlYQmdjbXIzb2N0Q2dQeVBnQUtEc0ktQ3dpZHRjTHlpWV9FaVpvQkNnUHlQZ0FLRHNJLUN3aW4wN2ZZbWZIVjVkVUJDZ1B5UGdBS0RjSS1DZ2pqNEstdl9ibWY0Z2dLQV9JLUFBb053ajRLQ0tqeDJfakowT0tlZlFvRDhqNEFDZzdDUGdzSXZvdmQ3X0dOOTdEWEFRb0Q4ajRBQ2czQ1Bnb0k0Y1hvektyVzFMWkJDZ1B5UGdBS0RjSS1DZ2pndWNfcXk4YkVneVFLQV9JLUFBb053ajRLQ1B2ZjAtcXMxdE90WlFvRDhqNEFDaUhTUGg0S0hGSkVRMDFWUTFoMWNWTkNiRWhCUlRaWWR5MTVaVXBCTUZSMWJuY0tBX0ktQUFvT3dqNExDTDZsdFl2ejZaQ2gyZ0VLQV9JLUFBb093ajRMQ0l6cnFkenM3NmJZMGdFS0FfSS1BQW9Pd2o0TENJUFNuOGpBbmRYYnNRRUtBX0ktQUFvT3dqNExDSXZEcXZidW9jamp6UUVLQV9JLUFBb093ajRMQ05HSXFzZVM5cUR2cFFFS0FfSS1BQW9Pd2o0TENNT2o4T3FwMVpIWDJBRUtBX0ktQUFvT3dqNExDSnJacHYyYzhfcW10d0VLQV9JLUFBb053ajRLQ1BmRGpKaTZzXy1ZUVJJVUFBSUVCZ2dLREE0UUVoUVdHQm9jSGlBaUpDWWFCQWdBRUFFYUJBZ0NFQU1hQkFnRUVBVWFCQWdHRUFjYUJBZ0lFQWthQkFnS0VBc2FCQWdNRUEwYUJBZ09FQThhQkFnUUVCRWFCQWdTRUJNYUJBZ1VFQlVhQkFnV0VCY2FCQWdZRUJrYUJBZ2FFQnNhQkFnY0VCMGFCQWdlRUI4YUJBZ2dFQ0VhQkFnaUVDTWFCQWdrRUNVYUJBZ21FQ2NxRkFBQ0JBWUlDZ3dPRUJJVUZoZ2FIQjRnSWlRbWoPd2F0Y2gtbmV4dC1mZWVk"),
visitor_data: Some("CgtIV0JjSUtDQm9LQSjUjpSZBg%3D%3D"),
endpoint: next,
),
top_comments: Paginator(
count: Some(2900),
items: [],
ctoken: Some("Eg0SC25GREJ4QlVmRTc0GAYyJSIRIgtuRkRCeEJVZkU3NDAAeAJCEGNvbW1lbnRzLXNlY3Rpb24%3D"),
endpoint: next,
),
latest_comments: Paginator(
count: Some(2900),
items: [],
ctoken: Some("Eg0SC25GREJ4QlVmRTc0GAYyOCIRIgtuRkRCeEJVZkU3NDABeAIwAUIhZW5nYWdlbWVudC1wYW5lbC1jb21tZW50cy1zZWN0aW9u"),
endpoint: next,
),
)

View file

@ -60,7 +60,7 @@ VideoDetails(
height: 176,
),
],
verification: verified,
verification: Verified,
subscriber_count: Some(5590000),
),
view_count: 681,
@ -73,7 +73,7 @@ VideoDetails(
recommended: Paginator(
count: None,
items: [
RecommendedVideo(
VideoItem(
id: "SGP6Y0Pnhe4",
title: "HOW IT WORKS: The International Space Station",
length: Some(1738),
@ -89,7 +89,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC_sXrcURB-Dh4az_FveeQ0Q",
name: "DOCUMENTARY TUBE",
avatar: [
@ -99,16 +99,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 years ago"),
view_count: 90280310,
view_count: Some(90280310),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "ddZu_1Z3BAc",
title: "NASA LIVE Stream From The ISS - Live Earth & Space Station Views & Audio",
length: None,
@ -124,7 +126,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCakgsb0w7QB0VHdnCc-OVEA",
name: "Space Videos",
avatar: [
@ -134,16 +136,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 80,
view_count: Some(80),
is_live: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "oDXBMjg9HKU",
title: "APOD: 2022-09-20 - Star Forming Region NGC 3582 without Stars (Narrated by Amy)",
length: Some(124),
@ -159,7 +163,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCZepiiyNNbD2XL5sWnJBC_A",
name: "Videotizer",
avatar: [
@ -169,16 +173,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("10 hours ago"),
view_count: 13,
view_count: Some(13),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "aU0vNvVHXa8",
title: "🌎 LIVE ASTEROID Watch Tracking",
length: None,
@ -194,7 +200,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCNrGOnduIS9BXIRmDcHasZA",
name: "WorldCam",
avatar: [
@ -204,16 +210,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 23,
view_count: Some(23),
is_live: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "6scCF_8YN70",
title: "Dramatic footage of the tsunami that hit Japan",
length: Some(133),
@ -229,7 +237,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCelk6aHijZq-GJBBB9YpReA",
name: "BBC News عربي",
avatar: [
@ -239,16 +247,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 years ago"),
view_count: 118635723,
view_count: Some(118635723),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "n4IhCSMkADc",
title: "EARTH FROM SPACE: Like You\'ve Never Seen Before",
length: Some(766),
@ -264,7 +274,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC_sXrcURB-Dh4az_FveeQ0Q",
name: "DOCUMENTARY TUBE",
avatar: [
@ -274,16 +284,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("7 years ago"),
view_count: 11226061,
view_count: Some(11226061),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "bgbH4FAmAA0",
title: "Winter Cab View from two of the most SCENIC RAILWAYS in the WORLD",
length: None,
@ -299,7 +311,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCj-Xm8j6WBgKY8OG7s9r2vQ",
name: "RailCowGirl",
avatar: [
@ -309,16 +321,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 108,
view_count: Some(108),
is_live: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "uD4izuDMUQA",
title: "TIMELAPSE OF THE FUTURE: A Journey to the End of Time (4K)",
length: Some(1761),
@ -334,7 +348,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCR9sFzaG9Ia_kXJhfxtFMBA",
name: "melodysheep",
avatar: [
@ -344,16 +358,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 85240979,
view_count: Some(85240979),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Z6DpPQ8QdLg",
title: "Earthrise - Planet Earth Seen From The Moon - Real Time Journey Across The Lunar Surface",
length: Some(241),
@ -369,7 +385,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCakgsb0w7QB0VHdnCc-OVEA",
name: "Space Videos",
avatar: [
@ -379,16 +395,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 years ago"),
view_count: 5405668,
view_count: Some(5405668),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "1hNF3Wuw0LI",
title: "New York City Walk 24/7 Chat Stream",
length: None,
@ -404,7 +422,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCRI_rCIV69l-PmT3oyD64kw",
name: "Afraz Explores",
avatar: [
@ -414,16 +432,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 10,
view_count: Some(10),
is_live: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "ZEyAs3NWH4A",
title: "New: Mars In 4K",
length: Some(609),
@ -439,7 +459,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCZvxw99l3xDC6BIHb8nJKGg",
name: "ElderFox Documentaries",
avatar: [
@ -449,16 +469,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 61247221,
view_count: Some(61247221),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "NF4LQaWJRDg",
title: "Hiroshima: Dropping the Bomb",
length: Some(276),
@ -474,7 +496,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC2ccm1GajfSujz7T18d7cKA",
name: "BBC Studios",
avatar: [
@ -484,16 +506,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("15 years ago"),
view_count: 36276575,
view_count: Some(36276575),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "qhOe_PxiNo8",
title: "Imagens, Talvez Inéditas do Tsunami no Japão",
length: Some(1202),
@ -509,7 +533,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCyrM5blUZAQoX9UvObdjtig",
name: "Valdemar Gomes",
avatar: [
@ -519,16 +543,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 years ago"),
view_count: 12004917,
view_count: Some(12004917),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "zf3bDpdhUNc",
title: "Astronauts accidentally lose a shield in space (GoPro 8K)",
length: Some(566),
@ -544,7 +570,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCgP30k64HHZ0OY1QkEgS6Pw",
name: "Waa Sop",
avatar: [
@ -554,16 +580,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 22901662,
view_count: Some(22901662),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "mJxsj51d-Pk",
title: "Record breaking space jump - free fall faster than speed of sound - Red Bull Stratos.",
length: Some(503),
@ -579,7 +607,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCBuDzfvztEJvNll_w1E9xFw",
name: "The Random Theorizer",
avatar: [
@ -589,16 +617,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 years ago"),
view_count: 42814880,
view_count: Some(42814880),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "fr_hXLDLc38",
title: "Horizons mission - Soyuz: launch to orbit",
length: Some(607),
@ -614,7 +644,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCIBaDdAbGlFDeS33shmlD0A",
name: "European Space Agency, ESA",
avatar: [
@ -624,16 +654,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 years ago"),
view_count: 9592134,
view_count: Some(9592134),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Jh-qzwdiAGY",
title: "The Earth 4K - Incredible 4K / UHD Video of Earth From Space",
length: Some(3594),
@ -649,7 +681,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCakgsb0w7QB0VHdnCc-OVEA",
name: "Space Videos",
avatar: [
@ -659,16 +691,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 years ago"),
view_count: 4463605,
view_count: Some(4463605),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "EPyl1LgNtoQ",
title: "The View from Space - Earth\'s Countries and Coastlines",
length: Some(227),
@ -684,7 +718,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC1znqKFL3jeR0eoA0pHpzvw",
name: "SpaceRip",
avatar: [
@ -694,16 +728,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("10 years ago"),
view_count: 14094460,
view_count: Some(14094460),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "7KXGZAEWzn0",
title: "ORBIT - Journey Around Earth in Real Time // 4K Remastered",
length: Some(5560),
@ -719,7 +755,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC28l88GMXXqZYfY0Ru9h50w",
name: "Seán Doran",
avatar: [
@ -729,16 +765,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 9901163,
view_count: Some(9901163),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "KTUa9rG08go",
title: "NASA Artemis I Mon Rocket Testing and Inspection LIVE From Launch Complex 39B",
length: None,
@ -754,7 +792,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCDyeuRnxf_hxEyH1B7aoDQQ",
name: "thebhp",
avatar: [
@ -764,26 +802,32 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: None,
view_count: 15,
view_count: Some(15),
is_live: true,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("CBQSExILODZZTEZPb2c0R03AAQHIAQEYACrgBzJzNkw2d3poQlFyZUJRb0Q4ajRBQ2czQ1Bnb0k3b3VlbjdUTV9yRklDZ1B5UGdBS0RjSS1DZ2lIaU55ejlkLWI2M1VLQV9JLUFBb093ajRMQ0tXNTlNR2pwdkNhb0FFS0FfSS1BQW9Od2o0S0NLLTduYXJ2NXN1bWFRb0Q4ajRBQ2c3Q1Bnc0l2ZV9nLVBfQ3dPUHFBUW9EOGo0QUNnN0NQZ3NJdDRDUW1aS2hpTUdmQVFvRDhqNEFDZzNDUGdvSWpZQ1lnWVg4c1lOdUNnUHlQZ0FLRHNJLUN3aUFvckdHN3RtSW43Z0JDZ1B5UGdBS0RjSS1DZ2k0NmNINDBLZTYwR2NLQV9JLUFBb093ajRMQ0xLaHc5M1d1OUdKMWdFS0FfSS1BQW9Od2o0S0NJQ18ySnEzbHFDbVpBb0Q4ajRBQ2czQ1Bnb0l1SWlsckpyb2dxODBDZ1B5UGdBS0RzSS1Dd2lQN1lqano5X25pYW9CQ2dQeVBnQUtEc0ktQ3dqWG9ZVzc2ZUgyX3MwQkNnUHlQZ0FLRHNJLUN3ajU4ZmZxLVpHYnpwZ0JDZ1B5UGdBS0RjSS1DZ2pfNXEyR3k2djQzMzRLQV9JLUFBb053ajRLQ09hQWlMdncyZXFQSmdvRDhqNEFDZzNDUGdvSWhPMjJ3TXU2cWY0UUNnUHlQZ0FLRHNJLUN3ajluTnVJd016eDB1d0JDZ1B5UGdBS0RjSS1DZ2lLNU5PTjY5N0dtaWtLQV9JLUFBb2FtajhYQ2hWUGZEazRNek0xTXpjMU5ERTJOVGMzT0RnMk1UY0tHNW9fR0FvV1Qzd3hNekF5TXpnek9UY3hPREk0TXpVMU9EUTFNd29ibWo4WUNoWlBmREUxT0RVek5Ua3dPRGczTURVeE1qVTBOemcwQ2dQeVBnQUtBX0ktQUJJWEFBSUVCZ2dLREE0UUVoUVdHQm9jSGlBaUpDWW9MQzBhQkFnQUVBRWFCQWdDRUFNYUJBZ0VFQVVhQkFnR0VBY2FCQWdJRUFrYUJBZ0tFQXNhQkFnTUVBMGFCQWdPRUE4YUJBZ1FFQkVhQkFnU0VCTWFCQWdVRUJVYUJBZ1dFQmNhQkFnWUVCa2FCQWdhRUJzYUJBZ2NFQjBhQkFnZUVCOGFCQWdnRUNFYUJBZ2lFQ01hQkFna0VDVWFCQWdtRUNjYUJBZ29FQ2thQkFnb0VDb2FCQWdvRUNzYUJBZ3NFQ2thQkFnc0VDb2FCQWdzRUNzYUJBZ3RFQ2thQkFndEVDb2FCQWd0RUNzcUZ3QUNCQVlJQ2d3T0VCSVVGaGdhSEI0Z0lpUW1LQ3d0ag93YXRjaC1uZXh0LWZlZWQ%3D"),
visitor_data: Some("CgtnQS1WdzlNNkNCSSiSmKiZBg%3D%3D"),
endpoint: next,
),
top_comments: Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: next,
),
latest_comments: Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: next,
),
)

View file

@ -28,7 +28,7 @@ VideoDetails(
height: 176,
),
],
verification: artist,
verification: Artist,
subscriber_count: Some(33900),
),
view_count: 20304,
@ -41,7 +41,7 @@ VideoDetails(
recommended: Paginator(
count: None,
items: [
RecommendedVideo(
VideoItem(
id: "XtV_HGppS6A",
title: "Vergiss mein nicht",
length: Some(263),
@ -57,7 +57,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -67,16 +67,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 30966,
view_count: Some(30966),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "BcqM8Qshx7U",
title: "Kuliko Jana - Eine neue Zeit",
length: Some(210),
@ -92,7 +94,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -102,16 +104,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 15269,
view_count: Some(15269),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "IUFUIgZOcow",
title: "Silmaril - Schöner als die Sterne",
length: Some(205),
@ -127,7 +131,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -137,16 +141,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 29035,
view_count: Some(29035),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "UtP9J88Jzg0",
title: "Ruinen im Sand",
length: Some(195),
@ -162,7 +168,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -172,16 +178,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 46009,
view_count: Some(46009),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "sg6j-zfUF_A",
title: "Eldamar",
length: Some(223),
@ -197,7 +205,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -207,16 +215,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 7405,
view_count: Some(7405),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "u2XCC1rKxV0",
title: "Faolan",
length: Some(256),
@ -232,7 +242,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -242,16 +252,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 19383,
view_count: Some(19383),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "oOBBBl3fywU",
title: "Aeria - Vom Wind",
length: Some(260),
@ -267,7 +279,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -277,16 +289,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 years ago"),
view_count: 132472,
view_count: Some(132472),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "pI0Rancanz0",
title: "Vergiss mein nicht",
length: Some(263),
@ -302,7 +316,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -312,16 +326,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 years ago"),
view_count: 367684,
view_count: Some(367684),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "DsviLYh1CB0",
title: "Eldamar",
length: Some(222),
@ -337,7 +353,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -347,16 +363,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 years ago"),
view_count: 195958,
view_count: Some(195958),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Ctpe9kafn78",
title: "So still mein Herz",
length: Some(259),
@ -372,7 +390,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -382,16 +400,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 37702,
view_count: Some(37702),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "y252630WbIk",
title: "Oonagh und Santiano: Vergiss mein nicht (mit lyrics)",
length: Some(260),
@ -407,7 +427,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC8mcGChRS6Zm7pCSYbHeoVw",
name: "princessZelda",
avatar: [
@ -417,16 +437,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("8 years ago"),
view_count: 103494,
view_count: Some(103494),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "YgUZtELr_jw",
title: "Aulë und Yavanna",
length: Some(216),
@ -442,7 +464,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -452,16 +474,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 19342,
view_count: Some(19342),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "ABKSs0aU4C0",
title: "Gäa (Akustik Version)",
length: Some(235),
@ -477,7 +501,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -487,16 +511,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 9392,
view_count: Some(9392),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "O0I3rJsHikA",
title: "Orome (A-Class Remix)",
length: Some(199),
@ -512,7 +538,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic",
avatar: [
@ -522,26 +548,32 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 22994,
view_count: Some(22994),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("CBQSExILWHVNMm9uTUd2VEnAAQHIAQEYACqsBzJzNkw2d3k2QlFxM0JRb0Q4ajRBQ2czQ1Bnb0lvSmVsMDhiajMtcGVDZ1B5UGdBS0o5SS1KQW9pVUV4aGFGSktXRWczV0ZCSWJWZE9TemMwVm5wM1NVWXljWFZYY1dSR1NWZDJjZ29EOGo0QUNpZlNQaVFLSWxCTU5pMTRZV3hIWVZaRmRYQjJlVGxHUVVoZlJYZ3pTRlYxWHpGaFVrRXlialFLQV9JLUFBb1MwajRQQ2cxU1JGaDFUVEp2YmsxSGRsUkpDZ1B5UGdBS0RjSS1DZ2kxajRmWmtKNmo1UVVLQV9JLUFBb053ajRLQ0l6bHViS2doTldnSVFvRDhqNEFDZzNDUGdvSWpaeW4tUHlrXy1sU0NnUHlQZ0FLRHNJLUN3andyOUMtc18tb2g3SUJDZ1B5UGdBS0o5SS1KQW9pVUV3d1dqSlNSVFZsY1dGWlRWRXhiRnBaZGtWalRrOW1UVmx3VFVvelkyTktRd29EOGo0QUNnN0NQZ3NJM1lxcjFyWEI4TEs3QVFvRDhqNEFDZzdDUGdzSWhaYl83dVdna1BDZ0FRb0Q4ajRBQ2c3Q1Bnc0l2YjdxdUtldHhNYWtBUW9EOGo0QUNnM0NQZ29JblpEVXc5akYtT1VPQ2dQeVBnQUtIOUktSEFvYVVrUkZUV1E0VUZwSmRqbERVSE4yZGtWRVltOWZjRlZFTkhjS0FfSS1BQW9Od2o0S0NMLV9fclRrM3BmdENnb0Q4ajRBQ2c3Q1Bnc0lpZG5aNkxmZG5iZkxBUW9EOGo0QUNnM0NQZ29JdlB5dmw4UzJ4b0ppQ2dQeVBnQUtETUktQ1FpdHdOTzB0TmFrQ1FvRDhqNEFDaWZTUGlRS0lsQk1NazR6TjFoVWQxaG5jRlZpYWxSemNXVjFNbEZFZVRCTGIyRnpkMDlZTVZvS0FfSS1BQW9Od2o0S0NNQ1VudGpKOVkyaE94SVVBQUlFQmdnS0RBNFFFaFFXR0JvY0hpQWlKQ1lhQkFnQUVBRWFCQWdDRUFNYUJBZ0VFQVVhQkFnR0VBY2FCQWdJRUFrYUJBZ0tFQXNhQkFnTUVBMGFCQWdPRUE4YUJBZ1FFQkVhQkFnU0VCTWFCQWdVRUJVYUJBZ1dFQmNhQkFnWUVCa2FCQWdhRUJzYUJBZ2NFQjBhQkFnZUVCOGFCQWdnRUNFYUJBZ2lFQ01hQkFna0VDVWFCQWdtRUNjcUZBQUNCQVlJQ2d3T0VCSVVGaGdhSEI0Z0lpUW1qD3dhdGNoLW5leHQtZmVlZA%3D%3D"),
visitor_data: Some("CgtzclhqZVpoajVhVSi76qeZBg%3D%3D"),
endpoint: next,
),
top_comments: Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: next,
),
latest_comments: Paginator(
count: Some(0),
items: [],
ctoken: None,
endpoint: next,
),
)

View file

@ -91,7 +91,7 @@ VideoDetails(
height: 176,
),
],
verification: verified,
verification: Verified,
subscriber_count: Some(30900000),
),
view_count: 232792465,
@ -104,7 +104,7 @@ VideoDetails(
recommended: Paginator(
count: None,
items: [
RecommendedVideo(
VideoItem(
id: "4TWR90KJl84",
title: "aespa 에스파 \'Next Level\' MV",
length: Some(236),
@ -120,7 +120,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -130,16 +130,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 245412217,
view_count: Some(245412217),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "WPdWvnAAurg",
title: "aespa 에스파 \'Savage\' MV",
length: Some(259),
@ -155,7 +157,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -165,16 +167,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("11 months ago"),
view_count: 215292736,
view_count: Some(215292736),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "NoYKBAajoyo",
title: "EVERGLOW (에버글로우) - DUN DUN MV",
length: Some(209),
@ -190,7 +194,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC_pwIXKXNm5KGhdEVzmY60A",
name: "Stone Music Entertainment",
avatar: [
@ -200,16 +204,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 264670229,
view_count: Some(264670229),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "KhTeiaCezwM",
title: "[MV] MAMAMOO (마마무) - HIP",
length: Some(211),
@ -225,7 +231,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCuhAUMLzJxlP1W7mEk0_6lA",
name: "MAMAMOO",
avatar: [
@ -235,16 +241,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 354281319,
view_count: Some(354281319),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Jh4QFaPmdss",
title: "(G)I-DLE - \'TOMBOY\' Official Music Video",
length: Some(198),
@ -260,7 +268,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCritGVo7pLJLUS8wEu32vow",
name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)",
avatar: [
@ -270,16 +278,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 months ago"),
view_count: 167648677,
view_count: Some(167648677),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "CM4CkVFmTds",
title: "TWICE \"I CAN\'T STOP ME\" M/V",
length: Some(221),
@ -295,7 +305,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -305,16 +315,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 455437333,
view_count: Some(455437333),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "uR8Mrt1IpXg",
title: "Red Velvet 레드벨벳 \'Psycho\' MV",
length: Some(216),
@ -330,7 +342,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -340,16 +352,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 344730852,
view_count: Some(344730852),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "QslJYDX3o8s",
title: "Red Velvet 레드벨벳 \'러시안 룰렛 (Russian Roulette)\' MV",
length: Some(212),
@ -365,7 +379,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -375,16 +389,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 years ago"),
view_count: 238321583,
view_count: Some(238321583),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "EaswWiwMVs8",
title: "Stray Kids \"소리꾼(Thunderous)\" M/V",
length: Some(199),
@ -400,7 +416,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -410,16 +426,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 240527435,
view_count: Some(240527435),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "pNfTK39k55U",
title: "ITZY \"달라달라(DALLA DALLA)\" M/V @ITZY",
length: Some(227),
@ -435,7 +453,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment",
avatar: [
@ -445,16 +463,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: 306144594,
view_count: Some(306144594),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "dYRITmpFbJ4",
title: "aespa 에스파 \'Girls\' MV",
length: Some(269),
@ -470,7 +490,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -480,16 +500,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 100128895,
view_count: Some(100128895),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "ioNng23DkIM",
title: "BLACKPINK - \'How You Like That\' M/V",
length: Some(184),
@ -505,7 +527,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -515,16 +537,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 1146631077,
view_count: Some(1146631077),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Ujb-gvqsoi0",
title: "Red Velvet - IRENE & SEULGI \'Monster\' MV",
length: Some(182),
@ -540,7 +564,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -550,16 +574,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: 126406160,
view_count: Some(126406160),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "bwmSjveL3Lc",
title: "BLACKPINK - \'붐바야 (BOOMBAYAH)\' M/V",
length: Some(244),
@ -575,7 +601,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK",
avatar: [
@ -585,16 +611,18 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("6 years ago"),
view_count: 1476093662,
view_count: Some(1476093662),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "6uJf2IT2Zh8",
title: "Red Velvet 레드벨벳 \'피카부 (Peek-A-Boo)\' MV",
length: Some(230),
@ -610,7 +638,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN",
avatar: [
@ -620,16 +648,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("4 years ago"),
view_count: 228968545,
view_count: Some(228968545),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "Y8JFxS1HlDo",
title: "IVE 아이브 \'LOVE DIVE\' MV",
length: Some(179),
@ -645,7 +675,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCYDmx2Sfpnaxg488yBpZIGg",
name: "starshipTV",
avatar: [
@ -655,16 +685,18 @@ VideoDetails(
height: 68,
),
],
verification: verified,
verification: Verified,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("5 months ago"),
view_count: 152292435,
view_count: Some(152292435),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "2FzSv66c7TQ",
title: "A E S P A (에스파) ALL SONGS PLAYLIST 2022 | 에스파 노래 모음",
length: Some(3441),
@ -680,7 +712,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UCK8S6QMrTk1G8TYQwIyDo-w",
name: "𝙇𝙌 𝙆𝙋𝙊𝙋",
avatar: [
@ -690,16 +722,18 @@ VideoDetails(
height: 68,
),
],
verification: none,
verification: None,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: 504562,
view_count: Some(504562),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
RecommendedVideo(
VideoItem(
id: "NU611fxGyPU",
title: "aespa 에스파 \'Black Mamba\' Dance Practice",
length: Some(175),
@ -715,7 +749,7 @@ VideoDetails(
height: 188,
),
],
channel: ChannelTag(
channel: Some(ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa",
avatar: [
@ -725,26 +759,32 @@ VideoDetails(
height: 68,
),
],
verification: artist,
verification: Artist,
subscriber_count: None,
),
)),
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: 34445393,
view_count: Some(34445393),
is_live: false,
is_short: false,
is_upcoming: false,
short_description: None,
),
],
ctoken: Some("CBQSExILWmVlcnJudUxpNUXAAQHIAQEYACq7BjJzNkw2d3psQkFyaUJBb0Q4ajRBQ2c3Q1Bnc0l6cS1tbFBTLTVKcmhBUW9EOGo0QUNoTFNQZzhLRFZKRVdtVmxjbkp1ZFV4cE5VVUtBX0ktQUFvdzBqNHRDaXRTUkVOTVFVczFkWGxmYXpJM2RYVXRSWFJSWDJJMVZUSnlNalpFVGtSYVQyMU9jVWRrWTJOVlNVZFJDZ1B5UGdBS0RjSS1DZ2k0OVlLQTU5ZlYtMWdLQV9JLUFBb053ajRLQ0tyR2pyWEF3SUxETmdvRDhqNEFDZzNDUGdvSWc1NzdoSnJSdDRvcUNnUHlQZ0FLRGNJLUNnakw3Wm1mMm9LRWp5WUtBX0ktQUFvTndqNEtDTnVibVl1VjBvRG5DQW9EOGo0QUNnN0NQZ3NJLU1xaTZ1MlZ3NC01QVFvRDhqNEFDZzNDUGdvSXk4ZmVyNE9zMHVSQ0NnUHlQZ0FLRGNJLUNnalByYkhnb292TTFSRUtBX0ktQUFvT3dqNExDSlhQa191MzVmVHJwQUVLQV9JLUFBb053ajRLQ0o3WmxkTG1pWkxDZFFvRDhqNEFDZzdDUGdzSWc2R083cmJ3MmNHS0FRb0Q4ajRBQ2czQ1Bnb0lyY1N5MWFfUXY1dFNDZ1B5UGdBS0RjSS1DZ2kzdWEtODc5SGtoRzhLQV9JLUFBb093ajRMQ0pfTTJhZUktNWZ4NmdFS0FfSS1BQW9Od2o0S0NMcW9udXJTdUpIaFl3b0Q4ajRBQ2c3Q1Bnc0l0TnJ6OVByWHRLN1lBUW9EOGo0QUNnM0NQZ29JOVpHYjR0LTZyYWMxRWhRQUFnUUdDQW9NRGhBU0ZCWVlHaHdlSUNJa0pob0VDQUFRQVJvRUNBSVFBeG9FQ0FRUUJSb0VDQVlRQnhvRUNBZ1FDUm9FQ0FvUUN4b0VDQXdRRFJvRUNBNFFEeG9FQ0JBUUVSb0VDQklRRXhvRUNCUVFGUm9FQ0JZUUZ4b0VDQmdRR1JvRUNCb1FHeG9FQ0J3UUhSb0VDQjRRSHhvRUNDQVFJUm9FQ0NJUUl4b0VDQ1FRSlJvRUNDWVFKeW9VQUFJRUJnZ0tEQTRRRWhRV0dCb2NIaUFpSkNZag93YXRjaC1uZXh0LWZlZWQ%3D"),
visitor_data: Some("Cgtjemd0bDVxU1N1QSjRjpSZBg%3D%3D"),
endpoint: next,
),
top_comments: Paginator(
count: Some(705000),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyJSIRIgtaZWVycm51TGk1RTAAeAJCEGNvbW1lbnRzLXNlY3Rpb24%3D"),
endpoint: next,
),
latest_comments: Paginator(
count: Some(705000),
items: [],
ctoken: Some("Eg0SC1plZXJybnVMaTVFGAYyOCIRIgtaZWVycm51TGk1RTABeAIwAUIhZW5nYWdlbWVudC1wYW5lbC1jb21tZW50cy1zZWN0aW9u"),
endpoint: next,
),
)

View file

@ -1,18 +1,15 @@
use crate::{
error::{Error, ExtractionError},
model::{Paginator, SearchVideo},
model::{Paginator, VideoItem},
param::Language,
serializer::MapResult,
util::TryRemove,
};
use super::{
response::{self, TryFromWLang},
ClientType, MapResponse, QBrowse, QContinuation, RustyPipeQuery,
};
use super::{response, ClientType, MapResponse, QBrowse, RustyPipeQuery};
impl RustyPipeQuery {
pub async fn startpage(self) -> Result<Paginator<SearchVideo>, Error> {
pub async fn startpage(self) -> Result<Paginator<VideoItem>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QBrowse {
context,
@ -29,33 +26,7 @@ impl RustyPipeQuery {
.await
}
pub async fn startpage_continuation(
self,
ctoken: &str,
visitor_data: &str,
) -> Result<Paginator<SearchVideo>, Error> {
let mut context = self.get_context(ClientType::Desktop, true).await;
context.client.visitor_data = Some(visitor_data.to_owned());
let request_body = QContinuation {
context,
continuation: ctoken,
};
self.execute_request::<response::StartpageCont, _, _>(
ClientType::Desktop,
"startpage_continuation",
ctoken,
"browse",
&request_body,
)
.await
.map(|res| Paginator {
visitor_data: Some(visitor_data.to_owned()),
..res
})
}
pub async fn trending(self) -> Result<Vec<SearchVideo>, Error> {
pub async fn trending(self) -> Result<Vec<VideoItem>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QBrowse {
context,
@ -73,20 +44,20 @@ impl RustyPipeQuery {
}
}
impl MapResponse<Paginator<SearchVideo>> for response::Startpage {
impl MapResponse<Paginator<VideoItem>> for response::Startpage {
fn map_response(
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Paginator<SearchVideo>>, ExtractionError> {
) -> Result<MapResult<Paginator<VideoItem>>, ExtractionError> {
let mut contents = self.contents.two_column_browse_results_renderer.tabs;
let grid = contents
.try_swap_remove(0)
.ok_or_else(|| ExtractionError::InvalidData("no contents".into()))?
.tab_renderer
.content
.rich_grid_renderer
.section_list_renderer
.contents;
Ok(map_startpage_videos(
@ -97,33 +68,15 @@ impl MapResponse<Paginator<SearchVideo>> for response::Startpage {
}
}
impl MapResponse<Paginator<SearchVideo>> for response::StartpageCont {
impl MapResponse<Vec<VideoItem>> for response::Trending {
fn map_response(
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Paginator<SearchVideo>>, ExtractionError> {
let mut received_actions = self.on_response_received_actions;
let items = received_actions
.try_swap_remove(0)
.ok_or_else(|| ExtractionError::InvalidData("no contents".into()))?
.append_continuation_items_action
.continuation_items;
Ok(map_startpage_videos(items, lang, None))
}
}
impl MapResponse<Vec<SearchVideo>> for response::Trending {
fn map_response(
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Vec<SearchVideo>>, ExtractionError> {
) -> Result<MapResult<Vec<VideoItem>>, ExtractionError> {
let mut contents = self.contents.two_column_browse_results_renderer.tabs;
let sections = contents
let items = contents
.try_swap_remove(0)
.ok_or_else(|| ExtractionError::InvalidData("no contents".into()))?
.tab_renderer
@ -131,76 +84,33 @@ impl MapResponse<Vec<SearchVideo>> for response::Trending {
.section_list_renderer
.contents;
let mut items = Vec::new();
let mut warnings = Vec::new();
let mut mapper = response::YouTubeListMapper::<VideoItem>::new(lang);
mapper.map_response(items);
for mut section in sections {
let shelf = section
.item_section_renderer
.contents
.try_swap_remove(0)
.and_then(|shelf| {
shelf
.shelf_renderer
.content
.expanded_shelf_contents_renderer
});
if let Some(mut shelf) = shelf {
warnings.append(&mut shelf.items.warnings);
for item in shelf.items.c {
if let response::trends::TrendingListItem::VideoRenderer(video) = item {
match SearchVideo::from_w_lang(video, lang) {
Ok(video) => {
items.push(video);
}
Err(e) => {
warnings.push(e.to_string());
}
}
}
}
}
}
Ok(MapResult { c: items, warnings })
Ok(MapResult {
c: mapper.items,
warnings: mapper.warnings,
})
}
}
fn map_startpage_videos(
videos: MapResult<Vec<response::VideoListItem>>,
videos: MapResult<Vec<response::YouTubeListItem>>,
lang: Language,
visitor_data: Option<String>,
) -> MapResult<Paginator<SearchVideo>> {
let mut warnings = videos.warnings;
let mut ctoken = None;
let items = videos
.c
.into_iter()
.filter_map(|item| match item {
response::VideoListItem::RichItemRenderer {
content: response::RichItem::VideoRenderer(video),
} => match SearchVideo::from_w_lang(video, lang) {
Ok(video) => Some(video),
Err(e) => {
warnings.push(e.to_string());
None
}
},
response::VideoListItem::ContinuationItemRenderer {
continuation_endpoint,
} => {
ctoken = Some(continuation_endpoint.continuation_command.token);
None
}
_ => None,
})
.collect();
) -> MapResult<Paginator<VideoItem>> {
let mut mapper = response::YouTubeListMapper::<VideoItem>::new(lang);
mapper.map_response(videos);
MapResult {
c: Paginator::new_with_vdata(None, items, ctoken, visitor_data),
warnings,
c: Paginator::new_ext(
None,
mapper.items,
mapper.ctoken,
visitor_data,
crate::param::ContinuationEndpoint::Browse,
),
warnings: mapper.warnings,
}
}
@ -210,7 +120,7 @@ mod tests {
use crate::{
client::{response, MapResponse},
model::{Paginator, SearchVideo},
model::{Paginator, VideoItem},
param::Language,
serializer::MapResult,
};
@ -223,7 +133,7 @@ mod tests {
let startpage: response::Startpage =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Paginator<SearchVideo>> =
let map_res: MapResult<Paginator<VideoItem>> =
startpage.map_response("", Language::En, None).unwrap();
assert!(
@ -237,28 +147,6 @@ mod tests {
});
}
#[test]
fn map_startpage_cont() {
let filename = "testfiles/trends/startpage_cont.json";
let json_path = Path::new(&filename);
let json_file = File::open(json_path).unwrap();
let startpage: response::StartpageCont =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Paginator<SearchVideo>> =
startpage.map_response("", Language::En, None).unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!("map_startpage_cont", map_res.c, {
".items[].publish_date" => "[date]",
});
}
#[test]
fn map_trending() {
let filename = "testfiles/trends/trending.json";
@ -267,7 +155,7 @@ mod tests {
let startpage: response::Trending =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Vec<SearchVideo>> =
let map_res: MapResult<Vec<VideoItem>> =
startpage.map_response("", Language::En, None).unwrap();
assert!(

View file

@ -2,7 +2,7 @@ use serde::Serialize;
use crate::{
error::{Error, ExtractionError},
model::{ChannelTag, Chapter, Comment, Paginator, RecommendedVideo, VideoDetails},
model::{ChannelTag, Chapter, Comment, Paginator, VideoDetails, VideoItem},
param::Language,
serializer::MapResult,
timeago,
@ -10,7 +10,7 @@ use crate::{
};
use super::{
response::{self, IconType, TryFromWLang},
response::{self, IconType},
ClientType, MapResponse, QContinuation, RustyPipeQuery, YTContext,
};
@ -45,28 +45,13 @@ impl RustyPipeQuery {
.await
}
pub async fn video_recommendations(
pub async fn video_comments(
self,
ctoken: &str,
) -> Result<Paginator<RecommendedVideo>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QContinuation {
context,
continuation: ctoken,
};
self.execute_request::<response::VideoRecommendations, _, _>(
ClientType::Desktop,
"video_recommendations",
ctoken,
"next",
&request_body,
)
.await
}
pub async fn video_comments(self, ctoken: &str) -> Result<Paginator<Comment>, Error> {
let context = self.get_context(ClientType::Desktop, true).await;
visitor_data: Option<&str>,
) -> Result<Paginator<Comment>, Error> {
let mut context = self.get_context(ClientType::Desktop, true).await;
context.client.visitor_data = visitor_data.map(str::to_owned);
let request_body = QContinuation {
context,
continuation: ctoken,
@ -254,7 +239,12 @@ impl MapResponse<VideoDetails> for response::VideoDetails {
.secondary_results
.and_then(|sr| {
sr.secondary_results.results.map(|r| {
let mut res = map_recommendations(r, sr.secondary_results.continuations, lang);
let mut res = map_recommendations(
r,
sr.secondary_results.continuations,
self.response_context.visitor_data,
lang,
);
warnings.append(&mut res.warnings);
res.c
})
@ -329,32 +319,26 @@ impl MapResponse<VideoDetails> for response::VideoDetails {
is_ccommons,
chapters,
recommended,
top_comments: Paginator::new(comment_count, Vec::new(), comment_ctoken),
latest_comments: Paginator::new(comment_count, Vec::new(), latest_comments_ctoken),
top_comments: Paginator::new_ext(
comment_count,
Vec::new(),
comment_ctoken,
None,
crate::param::ContinuationEndpoint::Next,
),
latest_comments: Paginator::new_ext(
comment_count,
Vec::new(),
latest_comments_ctoken,
None,
crate::param::ContinuationEndpoint::Next,
),
},
warnings,
})
}
}
impl MapResponse<Paginator<RecommendedVideo>> for response::VideoRecommendations {
fn map_response(
self,
_id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Paginator<RecommendedVideo>>, ExtractionError> {
let mut endpoints = self.on_response_received_endpoints;
let cont = endpoints.try_swap_remove(0).ok_or(ExtractionError::Retry)?;
Ok(map_recommendations(
cont.append_continuation_items_action.continuation_items,
None,
lang,
))
}
}
impl MapResponse<Paginator<Comment>> for response::VideoComments {
fn map_response(
self,
@ -362,9 +346,7 @@ impl MapResponse<Paginator<Comment>> for response::VideoComments {
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Paginator<Comment>>, ExtractionError> {
let received_endpoints = self
.on_response_received_endpoints
.ok_or(ExtractionError::Retry)?;
let received_endpoints = self.on_response_received_endpoints;
let mut warnings = received_endpoints.warnings;
let mut comments = Vec::new();
@ -419,47 +401,29 @@ impl MapResponse<Paginator<Comment>> for response::VideoComments {
}
fn map_recommendations(
r: MapResult<Vec<response::VideoListItem>>,
r: MapResult<Vec<response::YouTubeListItem>>,
continuations: Option<Vec<response::MusicContinuation>>,
visitor_data: Option<String>,
lang: Language,
) -> MapResult<Paginator<RecommendedVideo>> {
let mut warnings = r.warnings;
let mut ctoken = None;
let mut items = Vec::new();
r.c.into_iter().for_each(|item| match item {
response::VideoListItem::CompactVideoRenderer(video) => {
match RecommendedVideo::from_w_lang(video, lang) {
Ok(video) => items.push(video),
Err(e) => warnings.push(e.to_string()),
}
}
response::VideoListItem::ItemSectionRenderer { contents } => {
let mut x = map_recommendations(contents, None, lang);
items.append(&mut x.c.items);
warnings.append(&mut x.warnings);
if let Some(ct) = x.c.ctoken {
ctoken = Some(ct)
}
}
response::VideoListItem::ContinuationItemRenderer {
continuation_endpoint,
} => {
ctoken = Some(continuation_endpoint.continuation_command.token);
}
_ => {}
});
) -> MapResult<Paginator<VideoItem>> {
let mut mapper = response::YouTubeListMapper::<VideoItem>::new(lang);
mapper.map_response(r);
if let Some(continuations) = continuations {
continuations.into_iter().for_each(|c| {
ctoken = Some(c.next_continuation_data.continuation);
mapper.ctoken = Some(c.next_continuation_data.continuation);
})
};
MapResult {
c: Paginator::new(None, items, ctoken),
warnings,
c: Paginator::new_ext(
None,
mapper.items,
mapper.ctoken,
visitor_data,
crate::param::ContinuationEndpoint::Next,
),
warnings: mapper.warnings,
}
}
@ -600,42 +564,6 @@ mod tests {
))
}
#[test]
fn t_map_recommendations() {
let json_path = Path::new("testfiles/video_details/recommendations.json");
let json_file = File::open(json_path).unwrap();
let recommendations: response::VideoRecommendations =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res = recommendations
.map_response("", Language::En, None)
.unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!("map_recommendations", map_res.c, {
".items[].publish_date" => "[date]",
});
}
#[test]
fn map_recommendations_empty() {
let filename = format!("testfiles/video_details/recommendations_empty.json");
let json_path = Path::new(&filename);
let json_file = File::open(json_path).unwrap();
let recommendations: response::VideoRecommendations =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let err = recommendations
.map_response("", Language::En, None)
.unwrap_err();
assert!(matches!(err, crate::error::ExtractionError::Retry));
}
#[rstest]
#[case::top("top")]
#[case::latest("latest")]

View file

@ -83,6 +83,4 @@ pub enum ExtractionError {
WrongResult(String),
#[error("Warnings during deserialization/mapping")]
DeserializationWarnings,
#[error("Got no data from YouTube, attempt retry")]
Retry,
}

View file

@ -530,7 +530,7 @@ pub struct VideoDetails {
/// Recommended videos
///
/// Note: Recommendations are not available for age-restricted videos
pub recommended: Paginator<RecommendedVideo>,
pub recommended: Paginator<VideoItem>,
/// Paginator to fetch comments (most liked first)
///
/// Is initially empty.
@ -556,42 +556,6 @@ pub struct Chapter {
pub thumbnail: Vec<Thumbnail>,
}
/*
@RECOMMENDATIONS
*/
/// YouTube video fetched from the recommendations next to a video
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct RecommendedVideo {
/// Unique YouTube video ID
pub id: String,
/// Video title
pub title: String,
/// Video length in seconds.
///
/// Is [`None`] for livestreams.
pub length: Option<u32>,
/// Video thumbnail
pub thumbnail: Vec<Thumbnail>,
/// Channel of the video
pub channel: ChannelTag,
/// Video publishing date.
///
/// [`None`] if the date could not be parsed.
pub publish_date: Option<DateTime<Local>>,
/// Textual video publish date (e.g. `11 months ago`, depends on language)
///
/// Is [`None`] for livestreams.
pub publish_date_txt: Option<String>,
/// View count
pub view_count: u64,
/// Is the video an active livestream?
pub is_live: bool,
/// Is the video a YouTube Short video (vertical and <60s)?
pub is_short: bool,
}
/// Channel information attached to a video or comment
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
@ -618,7 +582,6 @@ pub struct ChannelTag {
/// Verification status of a channel
#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum Verification {
#[default]
@ -692,6 +655,8 @@ pub struct Channel<T> {
pub subscriber_count: Option<u64>,
/// Channel avatar / profile picture
pub avatar: Vec<Thumbnail>,
/// Channel verification mark
pub verification: Verification,
/// Channel description text
pub description: String,
/// List of words to describe the topic of the channel
@ -709,55 +674,6 @@ pub struct Channel<T> {
pub content: T,
}
/// Video fetched from a YouTube channel
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct ChannelVideo {
/// Unique YouTube video ID
pub id: String,
/// Video title
pub title: String,
/// Video length in seconds.
///
/// Is [`None`] for livestreams.
pub length: Option<u32>,
/// Video thumbnail
pub thumbnail: Vec<Thumbnail>,
/// Video publishing date.
///
/// [`None`] if the date could not be parsed.
/// May be in the future for upcoming videos
pub publish_date: Option<DateTime<Local>>,
/// Textual video publish date (e.g. `11 months ago`, depends on language)
///
/// Is [`None`] for livestreams and upcoming videos.
pub publish_date_txt: Option<String>,
/// Number of views / current viewers in case of a livestream.
///
/// [`None`] if it could not be extracted.
pub view_count: u64,
/// Is the video an active livestream?
pub is_live: bool,
/// Is the video a YouTube Short video (vertical and <60s)?
pub is_short: bool,
/// Is the video announced, but not released yet (YouTube Premiere)?
pub is_upcoming: bool,
}
/// Playlist fetched from a YouTube channel
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct ChannelPlaylist {
/// Unique YouTube Playlist-ID (e.g. `PL5dDx681T4bR7ZF1IuWzOv1omlRbE7PiJ`)
pub id: String,
/// Playlist name
pub name: String,
/// Playlist thumbnail
pub thumbnail: Vec<Thumbnail>,
/// Number of playlist videos
pub video_count: Option<u64>,
}
/// Additional channel metadata fetched from the "About" tab.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
@ -808,23 +724,34 @@ pub struct ChannelRssVideo {
pub like_count: u64,
}
/// YouTube search result
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SearchResult {
pub items: Paginator<SearchItem>,
/// Search result items
pub items: Paginator<YouTubeItem>,
/// Corrected search query
///
/// If the search term containes a typo, YouTube instead searches
/// for the corrected search term and displays it on top of the
/// search results page.
pub corrected_query: Option<String>,
}
/// YouTube item (Video/Channel/Playlist)
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum SearchItem {
Video(SearchVideo),
Playlist(SearchPlaylist),
Channel(SearchChannel),
pub enum YouTubeItem {
/// YouTube video item
Video(VideoItem),
/// YouTube playlist item
Playlist(PlaylistItem),
/// YouTube channel item
Channel(ChannelItem),
}
/// YouTube video from the search results
/// YouTube video list item
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct SearchVideo {
pub struct VideoItem {
/// Unique YouTube video ID
pub id: String,
/// Video title
@ -836,7 +763,7 @@ pub struct SearchVideo {
/// Video thumbnail
pub thumbnail: Vec<Thumbnail>,
/// Channel of the video
pub channel: ChannelTag,
pub channel: Option<ChannelTag>,
/// Video publishing date.
///
/// [`None`] if the date could not be parsed.
@ -848,43 +775,21 @@ pub struct SearchVideo {
/// View count
///
/// [`None`] if it could not be extracted.
pub view_count: u64,
pub view_count: Option<u64>,
/// Is the video an active livestream?
pub is_live: bool,
/// Is the video a YouTube Short video (vertical and <60s)?
pub is_short: bool,
/// Is the video announced, but not released yet (YouTube Premiere)?
pub is_upcoming: bool,
/// Abbreviated video description
pub short_description: String,
pub short_description: Option<String>,
}
/// Playlist from the search results
/// YouTube channel list item
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct SearchPlaylist {
/// Unique YouTube Playlist-ID (e.g. `PL5dDx681T4bR7ZF1IuWzOv1omlRbE7PiJ`)
pub id: String,
/// Playlist name
pub name: String,
/// Playlist thumbnail
pub thumbnail: Vec<Thumbnail>,
/// Number of playlist videos
pub video_count: u64,
/// First 2 videos
pub first_videos: Vec<SearchPlaylistVideo>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct SearchPlaylistVideo {
pub id: String,
pub title: String,
pub length: Option<u32>,
}
/// Channel from the search results
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct SearchChannel {
pub struct ChannelItem {
/// Unique YouTube channel ID
pub id: String,
/// Channel name
@ -902,3 +807,52 @@ pub struct SearchChannel {
/// Abbreviated channel description
pub short_description: String,
}
/// YouTube playlist list item
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct PlaylistItem {
/// Unique YouTube Playlist-ID (e.g. `PL5dDx681T4bR7ZF1IuWzOv1omlRbE7PiJ`)
pub id: String,
/// Playlist name
pub name: String,
/// Playlist thumbnail
pub thumbnail: Vec<Thumbnail>,
/// Channel of the playlist
pub channel: Option<ChannelTag>,
/// Number of playlist videos
pub video_count: Option<u64>,
}
impl TryFrom<YouTubeItem> for VideoItem {
type Error = ();
fn try_from(value: YouTubeItem) -> Result<Self, Self::Error> {
match value {
YouTubeItem::Video(video) => Ok(video),
_ => Err(()),
}
}
}
impl TryFrom<YouTubeItem> for PlaylistItem {
type Error = ();
fn try_from(value: YouTubeItem) -> Result<Self, Self::Error> {
match value {
YouTubeItem::Playlist(playlist) => Ok(playlist),
_ => Err(()),
}
}
}
impl TryFrom<YouTubeItem> for ChannelItem {
type Error = ();
fn try_from(value: YouTubeItem) -> Result<Self, Self::Error> {
match value {
YouTubeItem::Channel(channel) => Ok(channel),
_ => Err(()),
}
}
}

View file

@ -2,6 +2,8 @@ use std::convert::TryInto;
use serde::{Deserialize, Serialize};
use crate::param::ContinuationEndpoint;
/// Wrapper around progressively fetched items
///
/// The paginator is a wrapper around a list of items that are fetched
@ -31,6 +33,8 @@ pub struct Paginator<T> {
/// YouTube visitor data. Required for fetching the startpage
#[serde(skip_serializing_if = "Option::is_none")]
pub visitor_data: Option<String>,
/// YouTube API endpoint to fetch continuations from
pub endpoint: ContinuationEndpoint,
}
impl<T> Default for Paginator<T> {
@ -40,20 +44,22 @@ impl<T> Default for Paginator<T> {
items: Vec::new(),
ctoken: None,
visitor_data: None,
endpoint: ContinuationEndpoint::Browse,
}
}
}
impl<T> Paginator<T> {
pub(crate) fn new(count: Option<u64>, items: Vec<T>, ctoken: Option<String>) -> Self {
Self::new_with_vdata(count, items, ctoken, None)
Self::new_ext(count, items, ctoken, None, ContinuationEndpoint::Browse)
}
pub(crate) fn new_with_vdata(
pub(crate) fn new_ext(
count: Option<u64>,
items: Vec<T>,
ctoken: Option<String>,
visitor_data: Option<String>,
endpoint: ContinuationEndpoint,
) -> Self {
Self {
count: match ctoken {
@ -63,6 +69,7 @@ impl<T> Paginator<T> {
items,
ctoken,
visitor_data,
endpoint,
}
}

View file

@ -4,6 +4,7 @@ pub mod locale;
pub mod search_filter;
pub use locale::{Country, Language};
use serde::{Deserialize, Serialize};
pub use stream_filter::StreamFilter;
/// Channel video sort order
@ -18,3 +19,22 @@ pub enum ChannelOrder {
/// Output the most viewed videos first
Popular,
}
/// YouTube API endpoint to fetch continuations from
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ContinuationEndpoint {
Browse,
Search,
Next,
}
impl ContinuationEndpoint {
pub(crate) fn as_str(self) -> &'static str {
match self {
ContinuationEndpoint::Browse => "browse",
ContinuationEndpoint::Search => "search",
ContinuationEndpoint::Next => "next",
}
}
}

View file

@ -42,7 +42,7 @@ use crate::{
#[serde_as]
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum Text {
pub(crate) enum Text {
Simple {
#[serde(alias = "simpleText")]
text: String,
@ -86,10 +86,10 @@ impl<'de> DeserializeAs<'de, Vec<String>> for Text {
///
/// Texts with links are mapped as a list of text components.
#[derive(Default, Debug, Clone)]
pub struct TextComponents(pub Vec<TextComponent>);
pub(crate) struct TextComponents(pub Vec<TextComponent>);
#[derive(Debug, Clone)]
pub enum TextComponent {
pub(crate) enum TextComponent {
Video {
text: String,
video_id: String,
@ -130,7 +130,7 @@ struct RichTextRun {
/// the links.
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AttributedText {
pub(crate) struct AttributedText {
content: String,
#[serde(default)]
command_runs: Vec<AttributedTextRun>,
@ -345,7 +345,7 @@ impl From<TextComponents> for crate::model::richtext::RichText {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AccessibilityText {
pub(crate) struct AccessibilityText {
accessibility_data: AccessibilityData,
}

File diff suppressed because it is too large Load diff

View file

@ -1,94 +0,0 @@
{
"responseContext": {
"visitorData": "CgthSmp5T24zQkRjTSiom5WaBg%3D%3D",
"serviceTrackingParams": [
{
"service": "CSI",
"params": [
{
"key": "c",
"value": "WEB"
},
{
"key": "cver",
"value": "2.20221006.09.00"
},
{
"key": "yt_li",
"value": "0"
},
{
"key": "GetWatchNext_rid",
"value": "0x8836d1dc393da349"
}
]
},
{
"service": "GFEEDBACK",
"params": [
{
"key": "logged_in",
"value": "0"
},
{
"key": "e",
"value": "1714258,23804281,23882503,23885487,23918597,23934970,23940248,23946420,23966208,23983296,23986022,23998056,24001373,24002022,24002025,24004644,24007246,24034168,24036948,24077241,24080738,24108448,24120820,24135310,24140247,24152443,24161116,24162920,24164186,24166867,24169501,24181174,24185614,24187043,24187377,24191629,24197450,24199724,24199774,24211178,24217535,24219713,24223903,24224266,24225483,24226335,24227844,24228638,24229161,24241378,24243988,24248092,24248385,24254502,24255543,24255545,24256985,24259938,24260783,24262346,24263796,24265820,24267564,24267570,24268142,24268812,24268870,24278546,24278596,24279196,24279628,24279727,24280997,24281835,24282957,24283093,24283280,24286003,24286019,24287326,24287795,24288045,24289478,24289901,24289939,24290131,24290276,24290971,24292296,24295099,24295740,24297099,24298640,24298651,24298795,24299688,24299747,24390674,24391537,24392058,24392269,24394618,24590921,39322278,39322399,39322505"
}
]
},
{
"service": "GUIDED_HELP",
"params": [
{
"key": "logged_in",
"value": "0"
}
]
},
{
"service": "ECATCHER",
"params": [
{
"key": "client.version",
"value": "2.20221006"
},
{
"key": "client.name",
"value": "WEB"
},
{
"key": "client.fexp",
"value": "24286003,24298795,24256985,23804281,24001373,23946420,24283280,24289478,24223903,24298651,24286019,23885487,24077241,24265820,23918597,24255545,24036948,24259938,24279196,24199774,24282957,24279628,24268812,24169501,24225483,24590921,24197450,24298640,39322399,24290971,24108448,24287326,24219713,24278596,24002022,24181174,24227844,24287795,24229161,24283093,24162920,24248092,24241378,24166867,24002025,24280997,24391537,24278546,24288045,24034168,24290131,24211178,24289901,24226335,24268870,24295099,24135310,24191629,24394618,24007246,24004644,24243988,24281835,24392058,23998056,24185614,24262346,24187043,24224266,23986022,24228638,23934970,39322278,24292296,24260783,23940248,24263796,24267564,24299688,24390674,24152443,23966208,24267570,24080738,24290276,24217535,23882503,24279727,24164186,24289939,24187377,24268142,24120820,24199724,39322505,24392269,24254502,24255543,24299747,24161116,24140247,1714258,24297099,23983296,24295740,24248385"
}
]
}
],
"mainAppWebResponseContext": {
"loggedOut": true
},
"webResponseContextExtensionData": {
"hasDecorated": true
}
},
"trackingParams": "CAAQg2ciEwjfruPhg9j6AhXW2BEIHd9wAwc=",
"engagementPanels": [
{
"engagementPanelSectionListRenderer": {
"content": {
"adsEngagementPanelContentRenderer": {
"hack": true
}
},
"targetId": "engagement-panel-ads",
"visibility": "ENGAGEMENT_PANEL_VISIBILITY_HIDDEN",
"loggingDirectives": {
"trackingParams": "CAEQ040EGAAiEwjfruPhg9j6AhXW2BEIHd9wAwc=",
"visibility": {
"types": "12"
},
"enableDisplayloggerExperiment": true
}
}
}
]
}

View file

@ -7,7 +7,7 @@ use rustypipe::client::{ClientType, RustyPipe};
use rustypipe::error::{Error, ExtractionError};
use rustypipe::model::richtext::ToPlaintext;
use rustypipe::model::{
AudioCodec, AudioFormat, Channel, SearchItem, UrlTarget, Verification, VideoCodec, VideoFormat,
AudioCodec, AudioFormat, Channel, UrlTarget, Verification, VideoCodec, VideoFormat, YouTubeItem,
};
use rustypipe::param::{
search_filter::{self, SearchFilter},
@ -75,7 +75,7 @@ async fn get_player_from_client(#[case] client_type: ClientType) {
assert_eq!(video.codec, VideoCodec::Vp9);
assert_approx(audio.bitrate as f64, 130685.0);
assert_eq!(audio.average_bitrate, 129496);
assert_approx(audio.average_bitrate as f64, 129496.0);
assert_eq!(audio.size, 4193863);
assert_eq!(audio.mime, "audio/mp4; codecs=\"mp4a.40.2\"");
assert_eq!(audio.format, AudioFormat::M4a);
@ -154,7 +154,7 @@ async fn get_player_from_client(#[case] client_type: ClientType) {
#[case::live(
"86YLFOog4GM",
"🌎 Nasa Live Stream - Earth From Space : Live Views from the ISS",
"Live NASA - Views Of Earth from Space",
"The station is crewed by NASA astronauts as well as Russian Cosmonauts",
0,
"UCakgsb0w7QB0VHdnCc-OVEA",
"Space Videos",
@ -701,7 +701,7 @@ async fn get_video_details_live() {
);
let desc = details.description.to_plaintext();
assert!(
desc.contains("Live NASA - Views Of Earth from Space"),
desc.contains("The station is crewed by NASA astronauts as well as Russian Cosmonauts"),
"bad description: {}",
desc
);
@ -896,7 +896,7 @@ async fn channel_videos(#[case] order: ChannelOrder) {
}
ChannelOrder::Popular => {
assert!(
first_video.view_count > 2300000,
first_video.view_count.unwrap() > 2300000,
"most popular video < 2.3M views"
)
}
@ -984,6 +984,7 @@ fn assert_channel_eevblog<T>(channel: &Channel<T>) {
channel.subscriber_count.unwrap()
);
assert!(!channel.avatar.is_empty(), "got no thumbnails");
assert_eq!(channel.verification, Verification::Verified);
assert_eq!(channel.description, "NO SCRIPT, NO FEAR, ALL OPINION\nAn off-the-cuff Video Blog about Electronics Engineering, for engineers, hobbyists, enthusiasts, hackers and Makers\nHosted by Dave Jones from Sydney Australia\n\nDONATIONS:\nBitcoin: 3KqyH1U3qrMPnkLufM2oHDU7YB4zVZeFyZ\nEthereum: 0x99ccc4d2654ba40744a1f678d9868ecb15e91206\nPayPal: david@alternatezone.com\n\nPatreon: https://www.patreon.com/eevblog\n\nEEVblog2: http://www.youtube.com/EEVblog2\nEEVdiscover: https://www.youtube.com/channel/UCkGvUEt8iQLmq3aJIMjT2qQ\n\nEMAIL:\nAdvertising/Commercial: eevblog+business@gmail.com\nFan mail: eevblog+fan@gmail.com\nHate Mail: eevblog+hate@gmail.com\n\nI DON'T DO PAID VIDEO SPONSORSHIPS, DON'T ASK!\n\nPLEASE:\nDo NOT ask for personal advice on something, post it in the EEVblog forum.\nI read ALL email, but please don't be offended if I don't have time to reply, I get a LOT of email.\n\nMailbag\nPO Box 7949\nBaulkham Hills NSW 2153\nAUSTRALIA");
assert!(!channel.tags.is_empty(), "got no tags");
assert_eq!(
@ -1156,13 +1157,13 @@ async fn search_filter_entity(#[case] entity: search_filter::Entity) {
assert!(!result.items.is_exhausted());
result.items.items.iter().for_each(|item| match item {
SearchItem::Video(_) => {
YouTubeItem::Video(_) => {
assert_eq!(entity, search_filter::Entity::Video);
}
SearchItem::Channel(_) => {
YouTubeItem::Channel(_) => {
assert_eq!(entity, search_filter::Entity::Channel);
}
SearchItem::Playlist(_) => {
YouTubeItem::Playlist(_) => {
assert_eq!(entity, search_filter::Entity::Playlist);
}
});