feat: add channel playlists

- add tests for channel videos
- small model refactor (rename Channel to ChannelTag)
This commit is contained in:
ThetaDev 2022-09-26 20:36:01 +02:00
parent 45707c4d01
commit 6f1a1c4440
30 changed files with 16831 additions and 241 deletions

View file

@ -12,16 +12,16 @@ pub async fn download_testfiles(project_root: &Path) {
let mut testfiles = project_root.to_path_buf(); let mut testfiles = project_root.to_path_buf();
testfiles.push("testfiles"); testfiles.push("testfiles");
tokio::join!( player(&testfiles).await;
player(&testfiles), player_model(&testfiles).await;
player_model(&testfiles), playlist(&testfiles).await;
playlist(&testfiles), video_details(&testfiles).await;
video_details(&testfiles), comments_top(&testfiles).await;
comments_top(&testfiles), comments_latest(&testfiles).await;
comments_latest(&testfiles), recommendations(&testfiles).await;
recommendations(&testfiles), channel_videos(&testfiles).await;
channel_videos(&testfiles), channel_playlists(&testfiles).await;
); channel_info(&testfiles).await;
} }
const CLIENT_TYPES: [ClientType; 5] = [ const CLIENT_TYPES: [ClientType; 5] = [
@ -202,6 +202,7 @@ async fn channel_videos(testfiles: &Path) {
("music", "UC_vmjW5e1xEHhYjY2a0kK1A"), // YouTube Music channels have no videos ("music", "UC_vmjW5e1xEHhYjY2a0kK1A"), // YouTube Music channels have no videos
("shorts", "UCh8gHdtzO2tXd593_bjErWg"), // shorts and livestreams are rendered differently ("shorts", "UCh8gHdtzO2tXd593_bjErWg"), // shorts and livestreams are rendered differently
("live", "UChs0pSaEoNLV4mevBFGaoKA"), ("live", "UChs0pSaEoNLV4mevBFGaoKA"),
("empty", "UCxBa895m48H5idw5li7h-0g"),
] { ] {
let mut json_path = testfiles.to_path_buf(); let mut json_path = testfiles.to_path_buf();
json_path.push("channel"); json_path.push("channel");
@ -214,3 +215,33 @@ async fn channel_videos(testfiles: &Path) {
rp.query().channel_videos(id).await.unwrap(); rp.query().channel_videos(id).await.unwrap();
} }
} }
async fn channel_playlists(testfiles: &Path) {
let mut json_path = testfiles.to_path_buf();
json_path.push("channel");
json_path.push("channel_playlists.json");
if json_path.exists() {
return;
}
let rp = rp_testfile(&json_path);
rp.query()
.channel_playlists("UC2DjFE7Xf11URZqWBigcVOQ")
.await
.unwrap();
}
async fn channel_info(testfiles: &Path) {
let mut json_path = testfiles.to_path_buf();
json_path.push("channel");
json_path.push("channel_info.json");
if json_path.exists() {
return;
}
let rp = rp_testfile(&json_path);
rp.query()
.channel_info("UC2DjFE7Xf11URZqWBigcVOQ")
.await
.unwrap();
}

View file

@ -1,14 +1,21 @@
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use reqwest::Method; use reqwest::Method;
use serde::Serialize; use serde::Serialize;
use url::Url;
use crate::{ use crate::{
model::{ChannelVideos, Paginator}, model::{
Channel, ChannelInfo, ChannelOrder, ChannelPlaylist, ChannelVideo, Language, Paginator,
},
serializer::MapResult, serializer::MapResult,
util, timeago,
util::{self, TryRemove},
}; };
use super::{response, ClientType, MapResponse, RustyPipeQuery, YTContext}; use super::{
response::{self, IsLive, IsShort},
ClientType, MapResponse, RustyPipeQuery, YTContext,
};
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -33,12 +40,28 @@ enum Params {
} }
impl RustyPipeQuery { impl RustyPipeQuery {
pub async fn channel_videos(&self, channel_id: &str) -> Result<ChannelVideos> { pub async fn channel_videos(
&self,
channel_id: &str,
) -> Result<Channel<Paginator<ChannelVideo>>> {
self.channel_videos_ordered(channel_id, ChannelOrder::default())
.await
}
pub async fn channel_videos_ordered(
&self,
channel_id: &str,
order: ChannelOrder,
) -> Result<Channel<Paginator<ChannelVideo>>> {
let context = self.get_context(ClientType::Desktop, true).await; let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QChannel { let request_body = QChannel {
context, context,
browse_id: channel_id.to_owned(), browse_id: channel_id.to_owned(),
params: Params::VideosLatest, params: match order {
ChannelOrder::Latest => Params::VideosLatest,
ChannelOrder::Oldest => Params::VideosOldest,
ChannelOrder::Popular => Params::VideosPopular,
},
}; };
self.execute_request::<response::Channel, _, _>( self.execute_request::<response::Channel, _, _>(
@ -51,40 +74,493 @@ impl RustyPipeQuery {
) )
.await .await
} }
pub async fn channel_playlists(
&self,
channel_id: &str,
) -> Result<Channel<Paginator<ChannelPlaylist>>> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QChannel {
context,
browse_id: channel_id.to_owned(),
params: Params::Playlists,
};
self.execute_request::<response::Channel, _, _>(
ClientType::Desktop,
"channel_playlists",
channel_id,
Method::POST,
"browse",
&request_body,
)
.await
}
pub async fn channel_info(&self, channel_id: &str) -> Result<Channel<ChannelInfo>> {
let context = self.get_context(ClientType::Desktop, true).await;
let request_body = QChannel {
context,
browse_id: channel_id.to_owned(),
params: Params::Info,
};
self.execute_request::<response::Channel, _, _>(
ClientType::Desktop,
"channel_info",
channel_id,
Method::POST,
"browse",
&request_body,
)
.await
}
} }
impl MapResponse<ChannelVideos> for response::Channel { impl MapResponse<Channel<Paginator<ChannelVideo>>> for response::Channel {
fn map_response( fn map_response(
self, self,
id: &str, id: &str,
lang: crate::model::Language, lang: crate::model::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>, _deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<ChannelVideos>> { ) -> Result<MapResult<Channel<Paginator<ChannelVideo>>>> {
let warnings = Vec::new(); let content = map_channel_content(self.contents, id);
// dbg!(&self); let mut warnings = content.warnings;
let header = self.header.c4_tabbed_header_renderer; let grid = match content.c {
response::channel::ChannelContent::GridRenderer { items } => Some(items),
_ => None,
};
if header.channel_id != id { let mut v_res = grid.map(|g| map_videos(g, lang)).unwrap_or_default();
bail!( warnings.append(&mut v_res.warnings);
"got wrong channel id {}, expected {}",
header.channel_id,
id
);
}
Ok(MapResult { Ok(MapResult {
c: ChannelVideos { c: map_channel(
id: header.channel_id, self.header,
name: header.title, self.metadata,
subscriber_count: header self.microformat,
.subscriber_count_text v_res.c,
.and_then(|txt| util::parse_large_numstr(&txt, lang)), id,
videos: Paginator::default(), lang,
}, )?,
warnings: warnings,
})
}
}
impl MapResponse<Channel<Paginator<ChannelPlaylist>>> for response::Channel {
fn map_response(
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Channel<Paginator<ChannelPlaylist>>>> {
let content = map_channel_content(self.contents, id);
let mut warnings = content.warnings;
let grid = match content.c {
response::channel::ChannelContent::GridRenderer { items } => Some(items),
_ => None,
};
let mut p_res = grid.map(map_playlists).unwrap_or_default();
warnings.append(&mut p_res.warnings);
Ok(MapResult {
c: map_channel(
self.header,
self.metadata,
self.microformat,
p_res.c,
id,
lang,
)?,
warnings: warnings,
})
}
}
impl MapResponse<Channel<ChannelInfo>> for response::Channel {
fn map_response(
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
) -> Result<MapResult<Channel<ChannelInfo>>> {
let content = map_channel_content(self.contents, id);
let mut warnings = content.warnings;
let meta = match content.c {
response::channel::ChannelContent::ChannelAboutFullMetadataRenderer(meta) => Some(meta),
_ => None,
};
let cinfo = meta
.map(|meta| ChannelInfo {
create_date: timeago::parse_textual_date_or_warn(
lang,
&meta.joined_date_text,
&mut warnings,
),
view_count: util::parse_numeric_or_warn(&meta.view_count_text, &mut warnings),
links: meta
.primary_links
.into_iter()
.map(|l| {
(
l.title,
util::sanitize_yt_url(&l.navigation_endpoint.url_endpoint.url),
)
})
.collect(),
})
.unwrap_or_else(|| {
warnings.push("no metadata".to_owned());
ChannelInfo {
create_date: None,
view_count: None,
links: Vec::new(),
}
});
Ok(MapResult {
c: map_channel(
self.header,
self.metadata,
self.microformat,
cinfo,
id,
lang,
)?,
warnings, warnings,
}) })
} }
} }
fn map_videos(
res: MapResult<Vec<response::VideoListItem>>,
lang: Language,
) -> MapResult<Paginator<ChannelVideo>> {
let mut warnings = res.warnings;
let mut ctoken = None;
let videos = res
.c
.into_iter()
.filter_map(|item| match item {
response::VideoListItem::GridVideoRenderer(video) => {
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);
Some(ChannelVideo {
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
.published_time_text
.as_ref()
.and_then(|txt| timeago::parse_timeago_or_warn(lang, txt, &mut warnings)),
publish_date_txt: video.published_time_text,
view_count: video
.view_count_text
.map(|txt| util::parse_numeric(&txt).unwrap_or_default()),
is_live,
is_short,
})
}
response::VideoListItem::ContinuationItemRenderer {
continuation_endpoint,
} => {
ctoken = Some(continuation_endpoint.continuation_command.token);
None
}
_ => None,
})
.collect();
MapResult {
c: Paginator::new(None, videos, ctoken),
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(ChannelPlaylist {
id: playlist.playlist_id,
name: playlist.title,
thumbnail: playlist.thumbnail.into(),
video_count: util::parse_numeric(&playlist.video_count_short_text).ok(),
}),
response::VideoListItem::ContinuationItemRenderer {
continuation_endpoint,
} => {
ctoken = Some(continuation_endpoint.continuation_command.token);
None
}
_ => None,
})
.collect();
MapResult {
c: Paginator::new(None, playlists, ctoken),
warnings: res.warnings,
}
}
fn map_vanity_url(url: &str, id: &str) -> Option<String> {
if url.contains(id) {
return None;
}
let mut parsed_url = ok_or_bail!(Url::parse(url), None);
// The vanity URL from YouTube is http for some reason
let _ = parsed_url.set_scheme("https");
Some(parsed_url.to_string())
}
fn map_channel<T>(
header: response::channel::Header,
metadata: response::channel::Metadata,
microformat: response::channel::Microformat,
content: T,
id: &str,
lang: Language,
) -> Result<Channel<T>> {
let header = header.c4_tabbed_header_renderer;
if header.channel_id != id {
bail!(
"got wrong channel id {}, expected {}",
header.channel_id,
id
);
}
Ok(Channel {
id: header.channel_id,
name: header.title,
subscriber_count: header
.subscriber_count_text
.and_then(|txt| util::parse_large_numstr(&txt, lang)),
avatar: header.avatar.into(),
description: metadata.channel_metadata_renderer.description,
tags: microformat.microformat_data_renderer.tags,
vanity_url: metadata
.channel_metadata_renderer
.vanity_channel_url
.as_ref()
.and_then(|url| map_vanity_url(url, id)),
banner: header.banner.into(),
mobile_banner: header.mobile_banner.into(),
tv_banner: header.tv_banner.into(),
content,
})
}
fn map_channel_content(
contents: response::channel::Contents,
id: &str,
) -> MapResult<response::channel::ChannelContent> {
let mut tabs = contents.two_column_browse_results_renderer.tabs;
let mut sectionlist = some_or_bail!(
tabs.try_swap_remove(0),
MapResult::error("no tab".to_owned())
)
.tab_renderer
.content
.section_list_renderer;
if let Some(target_id) = sectionlist.target_id {
// YouTube falls back to the featured page if the channel does not have a "videos" tab.
// This is the case for YouTube Music channels.
if target_id.starts_with(&format!("browse-feed{}featured", id)) {
return MapResult::ok(response::channel::ChannelContent::None);
}
}
let mut itemsection = some_or_bail!(
sectionlist.contents.try_swap_remove(0),
MapResult::error("no sectionlist".to_owned())
)
.item_section_renderer
.contents;
let content = some_or_bail!(
itemsection.try_swap_remove(0),
MapResult::error("no channel content".to_owned())
);
MapResult::ok(content)
}
#[cfg(test)] #[cfg(test)]
mod tests {} mod tests {
use std::{fs::File, io::BufReader, path::Path};
use chrono::Datelike;
use rstest::rstest;
use crate::{
client::{response, MapResponse, RustyPipe},
model::{Channel, ChannelOrder, ChannelVideo, Language, Paginator},
serializer::MapResult,
};
#[rstest]
#[case::latest(ChannelOrder::Latest)]
#[case::oldest(ChannelOrder::Oldest)]
#[case::popular(ChannelOrder::Popular)]
#[tokio::test]
async fn get_videos(#[case] order: ChannelOrder) {
let rp = RustyPipe::builder().strict().build();
let channel = rp
.query()
.channel_videos_ordered("UC2DjFE7Xf11URZqWBigcVOQ", order)
.await
.unwrap();
// dbg!(&channel);
check_channel(&channel);
assert!(
!channel.content.items.is_empty() && !channel.content.is_exhausted(),
"got no videos"
);
let first_video = &channel.content.items[0];
let first_video_date = first_video.publish_date.unwrap();
let age_days = (chrono::Local::now() - first_video_date).num_days();
match order {
ChannelOrder::Latest => {
assert!(age_days < 60, "latest video older than 60 days")
}
ChannelOrder::Oldest => {
assert!(age_days > 4700, "oldest video newer than 4700 days")
}
ChannelOrder::Popular => {
assert!(
first_video.view_count.unwrap() > 2300000,
"most popular video < 2.3M views"
)
}
}
}
#[tokio::test]
async fn get_playlists() {
let rp = RustyPipe::builder().strict().build();
let channel = rp
.query()
.channel_playlists("UC2DjFE7Xf11URZqWBigcVOQ")
.await
.unwrap();
// dbg!(&channel);
check_channel(&channel);
assert!(
!channel.content.items.is_empty() && !channel.content.is_exhausted(),
"got no playlists"
);
}
#[tokio::test]
async fn get_info() {
let rp = RustyPipe::builder().strict().build();
let channel = rp
.query()
.channel_info("UC2DjFE7Xf11URZqWBigcVOQ")
.await
.unwrap();
dbg!(&channel);
check_channel(&channel);
let created = channel.content.create_date.unwrap();
assert_eq!(created.year(), 2009);
assert_eq!(created.month(), 4);
assert_eq!(created.day(), 4);
assert!(
channel.content.view_count.unwrap() > 186854340,
"exp >186M views, got {}",
channel.content.view_count.unwrap()
);
insta::assert_ron_snapshot!(channel.content.links, @r###"
[
("EEVblog Web Site", "http://www.eevblog.com/"),
("Twitter", "http://www.twitter.com/eevblog"),
("Facebook", "http://www.facebook.com/EEVblog"),
("EEVdiscover", "https://www.youtube.com/channel/UCkGvUEt8iQLmq3aJIMjT2qQ"),
("The EEVblog Forum", "http://www.eevblog.com/forum"),
("EEVblog Merchandise (T-Shirts)", "http://www.eevblog.com/merch"),
("EEVblog Donations", "http://www.eevblog.com/donations/"),
("Patreon", "https://www.patreon.com/eevblog"),
("SubscribeStar", "https://www.subscribestar.com/eevblog"),
("The AmpHour Radio Show", "http://www.theamphour.com/"),
("Flickr", "http://www.flickr.com/photos/eevblog"),
("EEVblog AMAZON Store", "http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2F&tag=ee04-20&linkCode=ur2&camp=1789&creative=390957"),
("2nd EEVblog Channel", "http://www.youtube.com/EEVblog2"),
]
"###);
}
fn check_channel<T>(channel: &Channel<T>) {
assert_eq!(channel.id, "UC2DjFE7Xf11URZqWBigcVOQ");
assert_eq!(channel.name, "EEVblog");
assert!(
channel.subscriber_count.unwrap() > 880000,
"exp >880K subscribers, got {}",
channel.subscriber_count.unwrap()
);
assert!(!channel.avatar.is_empty(), "got no thumbnails");
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!(
channel.vanity_url.as_ref().unwrap(),
"https://www.youtube.com/c/EevblogDave"
);
assert!(!channel.banner.is_empty(), "got no banners");
assert!(!channel.mobile_banner.is_empty(), "got no mobile banners");
assert!(!channel.tv_banner.is_empty(), "got no tv banners");
}
#[rstest]
#[case::base("base", "UC2DjFE7Xf11URZqWBigcVOQ")]
#[case::music("music", "UC_vmjW5e1xEHhYjY2a0kK1A")]
#[case::shorts("shorts", "UCh8gHdtzO2tXd593_bjErWg")]
#[case::live("live", "UChs0pSaEoNLV4mevBFGaoKA")]
#[case::empty("empty", "UCxBa895m48H5idw5li7h-0g")]
fn t_map_channel_videos(#[case] name: &str, #[case] id: &str) {
let filename = format!("testfiles/channel/channel_videos_{}.json", name);
let json_path = Path::new(&filename);
let json_file = File::open(json_path).unwrap();
let channel: response::Channel =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res: MapResult<Channel<Paginator<ChannelVideo>>> =
channel.map_response(id, Language::En, None).unwrap();
assert!(
map_res.warnings.is_empty(),
"deserialization/mapping warnings: {:?}",
map_res.warnings
);
insta::assert_ron_snapshot!(format!("map_channel_videos_{}", name), map_res.c, {
".content.items[].publish_date" => "[date]",
});
}
}

View file

@ -7,8 +7,9 @@ use anyhow::{anyhow, bail, Result};
use chrono::{Local, NaiveDateTime, NaiveTime, TimeZone}; use chrono::{Local, NaiveDateTime, NaiveTime, TimeZone};
use fancy_regex::Regex; use fancy_regex::Regex;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use reqwest::{Method, Url}; use reqwest::Method;
use serde::Serialize; use serde::Serialize;
use url::Url;
use crate::{ use crate::{
deobfuscate::Deobfuscator, deobfuscate::Deobfuscator,
@ -174,7 +175,7 @@ impl MapResponse<VideoPlayer> for response::Player {
title: video_details.title, title: video_details.title,
description: video_details.short_description, description: video_details.short_description,
length: video_details.length_seconds, length: video_details.length_seconds,
thumbnails: video_details.thumbnail.unwrap_or_default().into(), thumbnails: video_details.thumbnail.into(),
channel: ChannelId { channel: ChannelId {
id: video_details.channel_id, id: video_details.channel_id,
name: video_details.author, name: video_details.author,

View file

@ -5,13 +5,17 @@ use serde_with::VecSkipError;
use super::ChannelBadge; use super::ChannelBadge;
use super::Thumbnails; use super::Thumbnails;
use super::{ContentRenderer, ContentsRenderer, VideoListItem}; use super::{ContentRenderer, ContentsRenderer, VideoListItem};
use crate::serializer::ignore_any;
use crate::serializer::{text::Text, MapResult, VecLogError}; use crate::serializer::{text::Text, MapResult, VecLogError};
#[serde_as]
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Channel { pub struct Channel {
pub header: Header, pub header: Header,
pub contents: Contents, pub contents: Contents,
pub metadata: Metadata,
pub microformat: Microformat,
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
@ -46,27 +50,30 @@ pub struct SectionListRendererWrap {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SectionListRenderer { pub struct SectionListRenderer {
pub contents: Vec<ItemSectionRendererWrap>, pub contents: Vec<ItemSectionRendererWrap>,
pub target_id: String, /// - **Videos**: browse-feedUC2DjFE7Xf11URZqWBigcVOQvideos (...)
/// - **Playlists**: browse-feedUC2DjFE7Xf11URZqWBigcVOQplaylists104 (...)
/// - **Info**: None
pub target_id: Option<String>,
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ItemSectionRendererWrap { pub struct ItemSectionRendererWrap {
pub item_section_renderer: ContentsRenderer<GridRendererWrap>, pub item_section_renderer: ContentsRenderer<ChannelContent>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GridRendererWrap {
pub grid_renderer: GridRenderer,
} }
#[serde_as] #[serde_as]
#[derive(Clone, Debug, Deserialize)] #[derive(Default, Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GridRenderer { pub enum ChannelContent {
#[serde_as(as = "VecLogError<_>")] GridRenderer {
pub items: MapResult<Vec<VideoListItem>>, #[serde_as(as = "VecLogError<_>")]
items: MapResult<Vec<VideoListItem>>,
},
ChannelAboutFullMetadataRenderer(ChannelFullMetadata),
#[default]
#[serde(other, deserialize_with = "ignore_any")]
None,
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
@ -87,11 +94,74 @@ pub struct HeaderRenderer {
/// `None` if the subscriber count is hidden. /// `None` if the subscriber count is hidden.
#[serde_as(as = "Option<Text>")] #[serde_as(as = "Option<Text>")]
pub subscriber_count_text: Option<String>, pub subscriber_count_text: Option<String>,
#[serde(default)]
pub avatar: Thumbnails, pub avatar: Thumbnails,
#[serde_as(as = "Option<VecSkipError<_>>")] #[serde_as(as = "Option<VecSkipError<_>>")]
pub badges: Option<Vec<ChannelBadge>>, pub badges: Option<Vec<ChannelBadge>>,
#[serde(default)]
pub banner: Thumbnails, pub banner: Thumbnails,
#[serde(default)]
pub mobile_banner: Thumbnails, pub mobile_banner: Thumbnails,
/// Fullscreen (16:9) channel banner /// Fullscreen (16:9) channel banner
#[serde(default)]
pub tv_banner: Thumbnails, pub tv_banner: Thumbnails,
} }
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Metadata {
pub channel_metadata_renderer: ChannelMetadataRenderer,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelMetadataRenderer {
pub description: String,
pub vanity_channel_url: Option<String>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Microformat {
pub microformat_data_renderer: MicroformatDataRenderer,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MicroformatDataRenderer {
#[serde(default)]
pub tags: Vec<String>,
}
#[serde_as]
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelFullMetadata {
#[serde_as(as = "Text")]
pub joined_date_text: String,
#[serde_as(as = "Text")]
pub view_count_text: String,
#[serde_as(as = "VecSkipError<_>")]
pub primary_links: Vec<PrimaryLink>,
}
#[serde_as]
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PrimaryLink {
#[serde_as(as = "Text")]
pub title: String,
pub navigation_endpoint: NavigationEndpoint,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NavigationEndpoint {
pub url_endpoint: UrlEndpoint,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UrlEndpoint {
pub url: String,
}

View file

@ -37,6 +37,7 @@ pub struct ContentsRenderer<T> {
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ThumbnailsWrap { pub struct ThumbnailsWrap {
#[serde(default)]
pub thumbnail: Thumbnails, pub thumbnail: Thumbnails,
} }
@ -45,6 +46,7 @@ pub struct ThumbnailsWrap {
#[derive(Default, Clone, Debug, Deserialize)] #[derive(Default, Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Thumbnails { pub struct Thumbnails {
#[serde(default)]
pub thumbnails: Vec<Thumbnail>, pub thumbnails: Vec<Thumbnail>,
} }
@ -155,8 +157,6 @@ pub struct GridPlaylistRenderer {
pub title: String, pub title: String,
pub thumbnail: Thumbnails, pub thumbnail: Thumbnails,
#[serde_as(as = "Text")] #[serde_as(as = "Text")]
pub published_time_text: String,
#[serde_as(as = "Text")]
pub video_count_short_text: String, pub video_count_short_text: String,
} }
@ -244,6 +244,9 @@ pub struct TimeOverlay {
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct TimeOverlayRenderer { pub struct TimeOverlayRenderer {
/// `29:54`
///
/// Is `LIVE` in case of a livestream
#[serde_as(as = "Text")] #[serde_as(as = "Text")]
pub text: String, pub text: String,
#[serde(default)] #[serde(default)]

View file

@ -207,7 +207,8 @@ pub struct VideoDetails {
pub keywords: Option<Vec<String>>, pub keywords: Option<Vec<String>>,
pub channel_id: String, pub channel_id: String,
pub short_description: Option<String>, pub short_description: Option<String>,
pub thumbnail: Option<Thumbnails>, #[serde(default)]
pub thumbnail: Thumbnails,
#[serde_as(as = "JsonString")] #[serde_as(as = "JsonString")]
pub view_count: u64, pub view_count: u64,
pub author: String, pub author: String,

View file

@ -344,6 +344,7 @@ pub struct MacroMarkersListItem {
pub struct MacroMarkersListItemRenderer { pub struct MacroMarkersListItemRenderer {
/// Contains chapter start time in seconds /// Contains chapter start time in seconds
pub on_tap: MacroMarkersListItemOnTap, pub on_tap: MacroMarkersListItemOnTap,
#[serde(default)]
pub thumbnail: Thumbnails, pub thumbnail: Thumbnails,
/// Chapter title /// Chapter title
#[serde_as(as = "Text")] #[serde_as(as = "Text")]
@ -528,6 +529,7 @@ pub struct CommentRenderer {
#[serde(default)] #[serde(default)]
#[serde_as(as = "DefaultOnError<Option<Text>>")] #[serde_as(as = "DefaultOnError<Option<Text>>")]
pub author_text: Option<String>, pub author_text: Option<String>,
#[serde(default)]
pub author_thumbnail: Thumbnails, pub author_thumbnail: Thumbnails,
#[serde(default)] #[serde(default)]
/// ID of the author's channel /// ID of the author's channel

View file

@ -0,0 +1,37 @@
---
source: src/client/channel.rs
expression: map_res.c
---
Channel(
id: "UCxBa895m48H5idw5li7h-0g",
name: "Sebastian Figurroa",
subscriber_count: None,
avatar: [
Thumbnail(
url: "https://yt3.ggpht.com/ytc/AMLnZu_hsZ1XlUXHzXsGNHJw0np79WhWZcC4j8eFdy-tiUCDBKAjJyJOzE5kXFRiqL2S=s48-c-k-c0x00ffffff-no-rj",
width: 48,
height: 48,
),
Thumbnail(
url: "https://yt3.ggpht.com/ytc/AMLnZu_hsZ1XlUXHzXsGNHJw0np79WhWZcC4j8eFdy-tiUCDBKAjJyJOzE5kXFRiqL2S=s88-c-k-c0x00ffffff-no-rj",
width: 88,
height: 88,
),
Thumbnail(
url: "https://yt3.ggpht.com/ytc/AMLnZu_hsZ1XlUXHzXsGNHJw0np79WhWZcC4j8eFdy-tiUCDBKAjJyJOzE5kXFRiqL2S=s176-c-k-c0x00ffffff-no-rj",
width: 176,
height: 176,
),
],
description: "",
tags: [],
vanity_url: None,
banner: [],
mobile_banner: [],
tv_banner: [],
content: Paginator(
count: Some(0),
items: [],
ctoken: None,
),
)

View file

@ -0,0 +1,806 @@
---
source: src/client/channel.rs
expression: map_res.c
---
Channel(
id: "UChs0pSaEoNLV4mevBFGaoKA",
name: "The Good Life Radio x Sensual Musique",
subscriber_count: Some(760000),
avatar: [
Thumbnail(
url: "https://yt3.ggpht.com/ytc/AMLnZu_V9mOdHaorjNFqGXCecFeOBZhDWB8tVYG_I8gJwA=s48-c-k-c0x00ffffff-no-rj",
width: 48,
height: 48,
),
Thumbnail(
url: "https://yt3.ggpht.com/ytc/AMLnZu_V9mOdHaorjNFqGXCecFeOBZhDWB8tVYG_I8gJwA=s88-c-k-c0x00ffffff-no-rj",
width: 88,
height: 88,
),
Thumbnail(
url: "https://yt3.ggpht.com/ytc/AMLnZu_V9mOdHaorjNFqGXCecFeOBZhDWB8tVYG_I8gJwA=s176-c-k-c0x00ffffff-no-rj",
width: 176,
height: 176,
),
],
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",
"live stream",
"live radio",
"the good life radio",
"chill radio",
"chill music",
"chill-out music",
"music",
"live music",
"deep house",
"tropical house",
"house music",
],
vanity_url: Some("https://www.youtube.com/c/TheGoodLiferadio"),
banner: [
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w1060-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1060,
height: 175,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w1138-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1138,
height: 188,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w1707-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1707,
height: 283,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w2120-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2120,
height: 351,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w2276-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2276,
height: 377,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2560,
height: 424,
),
],
mobile_banner: [
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w320-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 320,
height: 88,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w640-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 640,
height: 175,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w960-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 960,
height: 263,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w1280-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 1280,
height: 351,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w1440-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 1440,
height: 395,
),
],
tv_banner: [
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 320,
height: 180,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 854,
height: 480,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 1280,
height: 720,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 1920,
height: 1080,
),
Thumbnail(
url: "https://yt3.ggpht.com/fL4x31Q80O_BvnhVIMI9YlV3apsiFvBENwGiSA-Hw9An6djAGw92RSOFax6z2r_rJNbRWPMA=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 2120,
height: 1192,
),
],
content: Paginator(
count: Some(21),
items: [
ChannelVideo(
id: "csP93FGy0bs",
title: "Chill Out Music Mix • 24/7 Live Radio | Relaxing Deep House, Chillout Lounge, Vocal & Instrumental",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/csP93FGy0bs/hqdefault_live.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDq5TEpXIGH_OHZhn2_Jx7lp2kMUQ",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/csP93FGy0bs/hqdefault_live.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLC9qL4JVwhDYjLBx6SvJHk6W92nqw",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/csP93FGy0bs/hqdefault_live.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLB4ocU3LUEK0_pKLnGDc4VktaxXiQ",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/csP93FGy0bs/hqdefault_live.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCXgkgVSHFrMa8V8N5v2UjWO28hsA",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: None,
view_count: Some(94),
is_live: true,
is_short: false,
),
ChannelVideo(
id: "19hKXI1ENrY",
title: "Deep House Radio | Relaxing & Chill House, Best Summer Mix 2022, Gym & Workout Music",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/19hKXI1ENrY/hqdefault_live.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAmi9jgARxMYdZpIOLw5RhQkRx0Dg",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/19hKXI1ENrY/hqdefault_live.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBsgHDcgMqq7QY7EzTfkqRlgQnctQ",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/19hKXI1ENrY/hqdefault_live.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBUlUVC0PKWdLgAIuM-plZNXvLCpw",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/19hKXI1ENrY/hqdefault_live.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDKTKtHa8U33nGE3z90NHdw1hg0gA",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: None,
view_count: Some(381),
is_live: true,
is_short: false,
),
ChannelVideo(
id: "CqMUC5eXX7c",
title: "Back To School / Work 📚 Deep Focus Chillout Mix | The Good Life Radio #4",
length: Some(4667),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/CqMUC5eXX7c/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDJglNaF89w0KFxzGn4Y3UAwu9ydg",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/CqMUC5eXX7c/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBUInjw2qHf7fffZFisSpebAZx4ZQ",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/CqMUC5eXX7c/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLChdljUBQgZrwYI4X1iHOFLqJFleg",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/CqMUC5eXX7c/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCP-eLq1BjkztFjdvT9oDC28CQ0Ig",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: Some(241528),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "A77SYlXKQEM",
title: "Chillout Lounge 🏖\u{fe0f} Calm & Relaxing Background Music | The Good Life Radio #3",
length: Some(1861),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/A77SYlXKQEM/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLA6c0iWB5IjXrbncP1JT2gvljTwyw",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/A77SYlXKQEM/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLC57WRX_9Q-NbZJM8BbSY4_exA-0w",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/A77SYlXKQEM/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDuYQKcxdJYJ70wktFpQ6PNLre4Kg",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/A77SYlXKQEM/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLC5AR1BxL-OKSWyAbDtVM1-riWmBA",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: Some(118351),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "72vkRHQfjbk",
title: "Summer Lovers 💖 A Beautiful & Relaxing Chillout Deep House Mix | The Good Life Radio #2",
length: Some(1832),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/72vkRHQfjbk/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBBMAUBpqHTq2IalWplaJugEhf4eQ",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/72vkRHQfjbk/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAUuACBQx4vbQhbtGEDOZp0L_pYOw",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/72vkRHQfjbk/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBsPzh5wHVrjbNpIPuxd0ZR5B5WUQ",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/72vkRHQfjbk/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBp4U-iN5-c9Y8F_8ojMY1RAyM9sg",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: Some(157971),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "AMWMDhibROw",
title: "Relaxing & Chill House 🌴 Summer \'21 Chill-Out Mix | The Good Life Radio #1",
length: Some(1949),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/AMWMDhibROw/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCDO-i7ZMHpgILmTxjIvtFEDl3fTQ",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/AMWMDhibROw/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAALFU5VLgPrCUeKWmZXTACCGwoLw",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/AMWMDhibROw/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLD_vOVH7ergjvzgGATU_PotDMRtRQ",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/AMWMDhibROw/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBZL8jux8zUDLrO428C6ZPzb5eppg",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 year ago"),
view_count: Some(82309),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "9UMxZofMNbA",
title: "Chillout Lounge - Calm & Relaxing Background Music | Study, Work, Sleep, Meditation, Chill",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/9UMxZofMNbA/hqdefault_live.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDc3KEjaAI_syibPmnpLN04x1Wv7g",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/9UMxZofMNbA/hqdefault_live.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDRgMqXrbV8u8WDQzqiod2XONVyCA",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/9UMxZofMNbA/hqdefault_live.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAdp0PT_vctOHl9kJI9M3GSTnvtgA",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/9UMxZofMNbA/hqdefault_live.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBwEl5g33rTRmvNLPTnYs9F8Tf0pg",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: None,
view_count: Some(2043),
is_live: true,
is_short: false,
),
ChannelVideo(
id: "a2sEYVwBvX4",
title: "Paratone - Heaven Is A Place On Earth (feat. kaii)",
length: Some(161),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/a2sEYVwBvX4/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBwBX3CEEc3ZK1SsP8iUbebtp5hUw",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/a2sEYVwBvX4/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCl_B8hp9iizLS28rJFG081PUwW_Q",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/a2sEYVwBvX4/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBUNlxWkdbMF_RwjZBztehCB73kvQ",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/a2sEYVwBvX4/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAwp0X-W_JovMyp4-2YhCrqv3kpTg",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(186475),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "JAY-prtJnGY",
title: "Joseph Feinstein - Where I Belong",
length: Some(126),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/JAY-prtJnGY/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLC79uFNaKWCm0lQ8_uxV0s2G0jJ-Q",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/JAY-prtJnGY/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLD5zFzigEu4lYRH-DU8QZOoGYqtSQ",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/JAY-prtJnGY/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLB2WhmMwj0Z5E-MYsyCcCBgYHYk-A",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/JAY-prtJnGY/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCl8HeilZsI4BEpGzgXezAcrNf6_w",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(66425),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "DySa8OrQDi4",
title: "LA Vision & Gigi D\'Agostino - Hollywood",
length: Some(200),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/DySa8OrQDi4/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAzPj5ZqrnaLQELc8EDtgLlUhDdRQ",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/DySa8OrQDi4/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCyVpPBISgyCbQofRmZ00ayOAdR7g",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/DySa8OrQDi4/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBSUtrS1H9zmYCwWVtpvNJs5YDFgA",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/DySa8OrQDi4/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAYq82JCAfQGWw72Y5uD5c4FqGzng",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(1520020),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "NqzXULaB8MA",
title: "LO - Home",
length: Some(163),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/NqzXULaB8MA/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDFvB5JbSQIUtb-pldtNWWHb2Y3SQ",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/NqzXULaB8MA/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAkMv60hZgnUzX6BPy439JVlC4qYA",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/NqzXULaB8MA/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLC_RMNhjVIE9uIoL2eUsCsgqz4osA",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/NqzXULaB8MA/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCvzbfRApS7SCw-mDrXBiOEVSiKng",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(37549),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "UGzy6uhZkmw",
title: "Luca - Sunset",
length: Some(153),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/UGzy6uhZkmw/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLD93d5foF1_yGd6ej5_8t-PM7ZCDw",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/UGzy6uhZkmw/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCqscP2y4jsbU5WUo8QcEVtcojQRQ",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/UGzy6uhZkmw/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBicCc5-9Cn7cyhzQXWRh-U1osFZw",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/UGzy6uhZkmw/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLClbjl9Zl8eWI-_QGEoaA6H2a-dRg",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(33002),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "iuvapHKpW8A",
title: "nourii - Better Off (feat. BCS)",
length: Some(126),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/iuvapHKpW8A/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCsDj4nWrDpmF-BTY_9REtx8xiHjA",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/iuvapHKpW8A/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAEqlsR_ujvaxo3po2UvHw10YpR4A",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/iuvapHKpW8A/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDL9vVk4L_OaiKxI_gT558zR108ow",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/iuvapHKpW8A/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLANK0ZOm-_hUACCRFBKHBgtcLCNMw",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(42036),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "n_1Nwht-Gh4",
title: "Deep House Covers & Remixes of Popular Songs 2020 🌴 Deep House, G-House, Chill-Out Music Playlist",
length: Some(2940),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/n_1Nwht-Gh4/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAwRnMWNt4fNmmGR4THSsTh-9MiCw",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/n_1Nwht-Gh4/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDFFVRUt-yQgt_-FWViG8gNyEet1g",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/n_1Nwht-Gh4/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCX7K2IMIJWSXr6yvcwqo2cte7kWw",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/n_1Nwht-Gh4/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDwJpjOiz8CUrGyd1SFGcwj_sSGNg",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(322935),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "6TptI5BtP5U",
title: "The Good Life Radio Mix #2 | Summer Memories ☀\u{fe0f} (Chill Music Playlist 2020)",
length: Some(3448),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/6TptI5BtP5U/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBGvxAmGVff9uk5AOxBij56uB6azw",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/6TptI5BtP5U/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCbAAXy7HAh6VkQdPvO4wm4pR7RQA",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/6TptI5BtP5U/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLB238nXmpbUcIcVEPy1uGwcJEvMuw",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/6TptI5BtP5U/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLANSe4a_jtstlVxx5-rkIOvbmuR8g",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(91980),
is_live: false,
is_short: false,
),
ChannelVideo(
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,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/36YnV9STBqc/hqdefault_live.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCe7OwcMt2h8bSNHbTTULV9-SST1Q",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/36YnV9STBqc/hqdefault_live.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAkzzBY_o86Nn0PbJftRE2t2NcUfQ",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/36YnV9STBqc/hqdefault_live.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBzzuLLFgJ072fAxz3yaAzkmnwJWA",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/36YnV9STBqc/hqdefault_live.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAeyiCUWTnj3nPmf80TIrS5zu9__g",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: None,
view_count: Some(4030),
is_live: true,
is_short: false,
),
ChannelVideo(
id: "7x6ii2TcsPE",
title: "The Good Life Radio Mix #1 | Relaxing & Chill House Music Playlist 2020",
length: Some(2726),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/7x6ii2TcsPE/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLC-CNpKCSMnLIscrYKNPX7DRZ0buA",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/7x6ii2TcsPE/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBzsfvaKcxkUInkuC4effHqf5E3HA",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/7x6ii2TcsPE/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAJLHolRQLl2mVsHhWMPTNeVbNQMg",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/7x6ii2TcsPE/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBSDc5C90T2SYrmMhqddmiKaGPAiA",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(288098),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "mxV5MBZYYDE",
title: "Christmas Music with Vocals 🎅 Best Relaxing Christmas Songs 2020",
length: Some(5863),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/mxV5MBZYYDE/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCVUbM3MtN0zZcE_8lY4eyo-Ly5Kw",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/mxV5MBZYYDE/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBajcqiVFnWHZXTBBO4Dzq-gDYDyg",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/mxV5MBZYYDE/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDbHzxHH7a4tjvIhH9DB3FYwihiyQ",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/mxV5MBZYYDE/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLD7NMECi-qMT4a_6fg9cOrc1C3-Ng",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(50818),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "hh2AOoPoAIo",
title: "The Good Life Radio Mix 2019 🎅 Winter & Christmas Relax House Playlist [Best of Part 1]",
length: Some(2530),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/hh2AOoPoAIo/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAMmrbiYHz-7STgazeW2PAuGCkCcg",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/hh2AOoPoAIo/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDKterYUnJQ9cm1HL9poDBtZenWXQ",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/hh2AOoPoAIo/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCKoxgX2sbbbLesBvjuOglua7pyPw",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/hh2AOoPoAIo/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCsqVhjHSvimVEEflkNZjqkfatEDQ",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 years ago"),
view_count: Some(98431),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "aFlvhtWsJ0g",
title: "Chillout Playlist | Relaxing Summer Music Mix 2019 [Deep & Tropical House]",
length: Some(2483),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/aFlvhtWsJ0g/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAvMC2I82wG7eQPDQmnyC3RbUGFWg",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/aFlvhtWsJ0g/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCBvVndf5HiT5-l-kuemFzm8JD3Sg",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/aFlvhtWsJ0g/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAOsKJmf_L47jJyyZssTbb-1adoSw",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/aFlvhtWsJ0g/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBsPLkhBu3g5BDQrs6YiMXhsLbS6Q",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: Some(572456),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "cD-d7u6fnEI",
title: "Chill House Playlist | Relaxing Summer Music 2019",
length: Some(3165),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/cD-d7u6fnEI/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBU_f1nTElkLg9ic2eKjM6luGgVcw",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/cD-d7u6fnEI/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCguCnp0eiwA3P2rcMehJFYhPYaVA",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/cD-d7u6fnEI/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBixvXbxOAuFROr670t_uM1eQr7FA",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/cD-d7u6fnEI/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLD0vklW2iG6fJ2aZOop8A7tQswm0g",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("3 years ago"),
view_count: Some(3114909),
is_live: false,
is_short: false,
),
],
ctoken: None,
),
)

View file

@ -0,0 +1,120 @@
---
source: src/client/channel.rs
expression: map_res.c
---
Channel(
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
name: "Oonagh - Topic",
subscriber_count: None,
avatar: [
Thumbnail(
url: "https://yt3.ggpht.com/pqKv4iqSjmMKPxsMCeyklTbpROSyInGNR4XvD1DqKD0AlROlsHzvoAlTvtMTO1g1x2WxaQ2Enxw=s48-c-k-c0x00ffffff-no-rj",
width: 48,
height: 48,
),
Thumbnail(
url: "https://yt3.ggpht.com/pqKv4iqSjmMKPxsMCeyklTbpROSyInGNR4XvD1DqKD0AlROlsHzvoAlTvtMTO1g1x2WxaQ2Enxw=s88-c-k-c0x00ffffff-no-rj",
width: 88,
height: 88,
),
Thumbnail(
url: "https://yt3.ggpht.com/pqKv4iqSjmMKPxsMCeyklTbpROSyInGNR4XvD1DqKD0AlROlsHzvoAlTvtMTO1g1x2WxaQ2Enxw=s176-c-k-c0x00ffffff-no-rj",
width: 176,
height: 176,
),
],
description: "",
tags: [],
vanity_url: None,
banner: [
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w1060-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1060,
height: 175,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w1138-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1138,
height: 188,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w1707-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1707,
height: 283,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w2120-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2120,
height: 351,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w2276-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2276,
height: 377,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2560,
height: 424,
),
],
mobile_banner: [
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w320-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 320,
height: 88,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w640-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 640,
height: 175,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w960-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 960,
height: 263,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w1280-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 1280,
height: 351,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w1440-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 1440,
height: 395,
),
],
tv_banner: [
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 320,
height: 180,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 854,
height: 480,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 1280,
height: 720,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 1920,
height: 1080,
),
Thumbnail(
url: "https://yt3.ggpht.com/EDatBjgcL94-qSfQa5Twr8l88hYcAXQJksDrwARWbotrWzJhG03gRyZLKV1mk1a1tMI_LSg4qg=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 2120,
height: 1192,
),
],
content: Paginator(
count: Some(0),
items: [],
ctoken: None,
),
)

View file

@ -0,0 +1,721 @@
---
source: src/client/channel.rs
expression: map_res.c
---
Channel(
id: "UCh8gHdtzO2tXd593_bjErWg",
name: "Doobydobap",
subscriber_count: Some(2840000),
avatar: [
Thumbnail(
url: "https://yt3.ggpht.com/dm5Aq93xvVJz0NoVO88ieBkDXmuShCujGPlZ7qETMEPTrXvPUCFI3-BB6Xs_P-r6Uk3mnBy9zA=s48-c-k-c0x00ffffff-no-rj",
width: 48,
height: 48,
),
Thumbnail(
url: "https://yt3.ggpht.com/dm5Aq93xvVJz0NoVO88ieBkDXmuShCujGPlZ7qETMEPTrXvPUCFI3-BB6Xs_P-r6Uk3mnBy9zA=s88-c-k-c0x00ffffff-no-rj",
width: 88,
height: 88,
),
Thumbnail(
url: "https://yt3.ggpht.com/dm5Aq93xvVJz0NoVO88ieBkDXmuShCujGPlZ7qETMEPTrXvPUCFI3-BB6Xs_P-r6Uk3mnBy9zA=s176-c-k-c0x00ffffff-no-rj",
width: 176,
height: 176,
),
],
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"),
banner: [
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w1060-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1060,
height: 175,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w1138-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1138,
height: 188,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w1707-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 1707,
height: 283,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w2120-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2120,
height: 351,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w2276-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2276,
height: 377,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
width: 2560,
height: 424,
),
],
mobile_banner: [
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w320-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 320,
height: 88,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w640-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 640,
height: 175,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w960-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 960,
height: 263,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w1280-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 1280,
height: 351,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w1440-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj",
width: 1440,
height: 395,
),
],
tv_banner: [
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 320,
height: 180,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 854,
height: 480,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 1280,
height: 720,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 1920,
height: 1080,
),
Thumbnail(
url: "https://yt3.ggpht.com/BvnAqgiursrXpmS9AgDLtkOSTQfOG_Dqn0KzY5hcwO9XrHTEQTVgaflI913f9KRp7d0U2qBp=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
width: 2120,
height: 1192,
),
],
content: Paginator(
count: None,
items: [
ChannelVideo(
id: "JBUZE0mIlg8",
title: "small but sure joy",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/JBUZE0mIlg8/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLCRBlyIUBUm_aypWz4tGkrDNJxIZw",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 day ago"),
view_count: Some(443549),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "SRrvxFc2b2c",
title: "i don\'t believe in long distance relationships",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/SRrvxFc2b2c/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLA0hJdOfUp-zMI-vW43sYnKgufocA",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 days ago"),
view_count: Some(1154962),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "l9TiwunjzgA",
title: "long distance",
length: Some(1043),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/l9TiwunjzgA/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDjM6SZ7ScyfFRr13QdVmIvWEWWrQ",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/l9TiwunjzgA/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDmjuvrAkYrdvhuU-Nl8jzx4so9oA",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/l9TiwunjzgA/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBJ5ZEDrtK_1oM20uRPmzPjDpUhrQ",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/l9TiwunjzgA/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCb6F-jiGZ5aYaq7HBh2if85d_t0A",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("3 days ago"),
view_count: Some(477460),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "cNx0ql9gnf4",
title: "come over :)",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/cNx0ql9gnf4/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLBvAKRZE2LyKIo6_6prX9pzfiWoVw",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("6 days ago"),
view_count: Some(1388173),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "fGQUWI4o__A",
title: "Baskin Robbins in South Korea",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/fGQUWI4o__A/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDyPuI762qzLAZM0QikxjFKVpoF9w",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("7 days ago"),
view_count: Some(1738301),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "Q73VTjdqVA8",
title: "dry hot pot",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/Q73VTjdqVA8/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLBfJXtFWfAnyMOvaJfvpYJ5WrhbSA",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("9 days ago"),
view_count: Some(1316594),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "pRVSdUxdsVw",
title: "Repairing...",
length: Some(965),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/pRVSdUxdsVw/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAQWneuYcJcccgooBfa3WI4LdYF3w",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/pRVSdUxdsVw/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAO8o5qPYTUPF4yyBLSpYBeE6lMSA",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/pRVSdUxdsVw/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLClJOy_nxUK-ACJUduXzk-khvwmpQ",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/pRVSdUxdsVw/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLB6k0Egq5r3hNjamUiia-lh-n2EEA",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("10 days ago"),
view_count: Some(478703),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "gTG2WDbiYGo",
title: "time machine",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/gTG2WDbiYGo/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDw5Lw19mNLJnoIF3aCGkMbxvgILQ",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("11 days ago"),
view_count: Some(1412213),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "y5JK5YFp92g",
title: "tiramissu",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/y5JK5YFp92g/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLCR66ytQIBWWw_ajvgyaUdUawHVIg",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("13 days ago"),
view_count: Some(1513305),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "pvSWHm4wlxY",
title: "having kids",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/pvSWHm4wlxY/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDt7ZAwQoObfa5A7gC_hJnU1WH4Ug",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: Some(8936223),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "2FJVhdOO0F0",
title: "a health scare",
length: Some(1238),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/2FJVhdOO0F0/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLA5ambaz-euRsB9VG5ANaYFUUSEbg",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/2FJVhdOO0F0/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBAbpE1_Iiqdmwbm_IbUFPxkyjmhg",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/2FJVhdOO0F0/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCLrwdM2QBdnaFPEpsmMVaAQq3vug",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/2FJVhdOO0F0/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAccJCJ5-5TLOBSooo4jeojbbfn9A",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: Some(987083),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "CqFGACRrWJE",
title: "just do it",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/CqFGACRrWJE/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDyAIF4S_foRXsyvq16YCPJWNKewQ",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 weeks ago"),
view_count: Some(2769717),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "CutR_1SDDzY",
title: "feels good to be back",
length: Some(1159),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/CutR_1SDDzY/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLAt413Uk4xhHjYwpLI5-DXuOsFouA",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/CutR_1SDDzY/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDd-m1YaVdVXcUh98FRzstRUn03Pw",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/CutR_1SDDzY/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBHgcMGTg11_LzuQOHo4oAUBtsfKg",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/CutR_1SDDzY/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDZtPA-3fS7BwVhuIHDbusLbw0Dqg",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: Some(497660),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "DdGr6t2NqKc",
title: "coming soon",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/DdGr6t2NqKc/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDRYfxh25EjK3zuOJORNNahxeBanA",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: Some(572107),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "jKS44NMWuXw",
title: "adult money",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/jKS44NMWuXw/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLAIexckdN7FXJUgkeJvITHyzXw1TQ",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: Some(1707132),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "kx1YtJM_vbI",
title: "a fig\'s journey",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/kx1YtJM_vbI/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLAi03nhSbt84LL7PFD2ij8GmaDlLQ",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("3 weeks ago"),
view_count: Some(933094),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "Sdbzs-1WWH0",
title: "How to.. Mozzarella 🧀",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/Sdbzs-1WWH0/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLC8IkwAif4wXhBGxHiosiILbPCSBw",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(5985184),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "9qBHyJIDous",
title: "how to drink like a real korean",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/9qBHyJIDous/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLB9Ib_E0siDiRMZ_GVHVxBfMd0Dkw",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(14741387),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "mBeFDb4gp8s",
title: "mr. krabs soup",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/mBeFDb4gp8s/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLCzAPzv16WTJLr4ma-sAz6fNkFL0g",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(2511322),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "b38r1UYqoBQ",
title: "in five years",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/b38r1UYqoBQ/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLCGB9IpC2Enx5iZ-YCl0vEpMGpo9A",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(2364408),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "KUz7oArksR4",
title: "running away",
length: Some(1023),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/KUz7oArksR4/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLD1NwuIgJuJy2oPAiHqMre6rbcuPA",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/KUz7oArksR4/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBW8VcMIUoAKbd8tNzfO1KmmZp9eA",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/KUz7oArksR4/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDr9DmdJzOC9_PIqkx2GO7xol_2vA",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/KUz7oArksR4/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLABH3-3faYHCYhoZUFbOey9w3HD2w",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(706059),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "RdFk4WaifEo",
title: "a weeknight dinner",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/RdFk4WaifEo/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLBlKLBjBagaTQj24nYb-HkCQQcWHA",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(1947627),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "GuyGyzZcumI",
title: "McDonald\'s Michelin Burger",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/GuyGyzZcumI/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDtmyilZAgMw8VWNy518etIKi4phA",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(4763839),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "07Zipsb3-qU",
title: "cwispy potato pancake",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/07Zipsb3-qU/hq720_2.jpg?sqp=-oaymwEdCJYDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLARXBTZlNStCVemXSkHfAWksRogng",
width: 406,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(1915695),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "3kaePnU6Clo",
title: "authenticity is overrated",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/3kaePnU6Clo/hq720_2.jpg?sqp=-oaymwEdCJYDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDq0MY9dsMvr9Y6yaJ7069fgtdpGA",
width: 406,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(7268944),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "rt4rXMftnpg",
title: "you can kimchi anything (T&C applies)",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/rt4rXMftnpg/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLC7WfSTGHkH2FEmn9gQ5E4AqpRtug",
width: 405,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("1 month ago"),
view_count: Some(2539103),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "DTyLUvbf128",
title: "egg, soy, and perfect pot rice",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/DTyLUvbf128/hq720_2.jpg?sqp=-oaymwEdCJYDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLAN1AtPya1D1NyiO0XYKOjIZIyhhQ",
width: 406,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: Some(5545680),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "DzjLBgIe_aI",
title: "love language",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/DzjLBgIe_aI/hq720_2.jpg?sqp=-oaymwEdCJYDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDWVkrYrt64LvvxrMRfs29g_lGrNw",
width: 406,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: Some(2202314),
is_live: false,
is_short: true,
),
ChannelVideo(
id: "sPb2gyN-hnE",
title: "worth fighting for",
length: Some(1232),
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/sPb2gyN-hnE/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBidXnS47SJMkvOlqt2DgzHxr6wKQ",
width: 168,
height: 94,
),
Thumbnail(
url: "https://i.ytimg.com/vi/sPb2gyN-hnE/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLCOxYF8A5DQVdZHh5O1vAdK-1qH1g",
width: 196,
height: 110,
),
Thumbnail(
url: "https://i.ytimg.com/vi/sPb2gyN-hnE/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBhQ9ZJs0bgGqdGb8t26tbjtmIKWA",
width: 246,
height: 138,
),
Thumbnail(
url: "https://i.ytimg.com/vi/sPb2gyN-hnE/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLB35l1byuqA4pkl2SzE8Cr0vmPVGg",
width: 336,
height: 188,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: Some(613416),
is_live: false,
is_short: false,
),
ChannelVideo(
id: "9JboRKeJ2m4",
title: "Rating Italian McDonald\'s",
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/9JboRKeJ2m4/hq720_2.jpg?sqp=-oaymwEdCJYDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLC7xktrbnAqJq2nHH9aDggULsb3Cg",
width: 406,
height: 720,
),
],
publish_date: "[date]",
publish_date_txt: Some("2 months ago"),
view_count: Some(6443699),
is_live: false,
is_short: true,
),
],
ctoken: Some("4qmFsgKrARIYVUNoOGdIZHR6TzJ0WGQ1OTNfYmpFcldnGmBFZ1oyYVdSbGIzTVlBeUFBTUFFNEFlb0RNRVZuYzBrM2NsTnVkazF4U1hWemRqQkJVMmQ1VFVGRk5FaHJTVXhEVUhac2NscHJSMFZKWVhWd016RkpRVlpCUVElM0QlM0SaAixicm93c2UtZmVlZFVDaDhnSGR0ek8ydFhkNTkzX2JqRXJXZ3ZpZGVvczEwMg%3D%3D"),
),
)

View file

@ -14,7 +14,7 @@ Paginator(
Text("🏻"), Text("🏻"),
Text("💗"), Text("💗"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCKv2ITDFlBf8sCaM4bGAq9w", id: "UCKv2ITDFlBf8sCaM4bGAq9w",
name: "rüyaabiee", name: "rüyaabiee",
avatar: [ avatar: [
@ -55,7 +55,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Mys, spotify wraps comes in a few months..so start str3ming Aespa all songs on spotify."), Text("Mys, spotify wraps comes in a few months..so start str3ming Aespa all songs on spotify."),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCpO0iV02gvz1zY0xaEip-Lw", id: "UCpO0iV02gvz1zY0xaEip-Lw",
name: "Ashdeep Sidashi", name: "Ashdeep Sidashi",
avatar: [ avatar: [
@ -97,7 +97,7 @@ Paginator(
Text("Cerita black mamba kan udah tutup buku. Kira2 nanti konsep comebacknya apa yaa? "), Text("Cerita black mamba kan udah tutup buku. Kira2 nanti konsep comebacknya apa yaa? "),
Text("😍"), Text("😍"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC8Uu90kmT1uBXMuylOe5F2g", id: "UC8Uu90kmT1uBXMuylOe5F2g",
name: "Ini Aku", name: "Ini Aku",
avatar: [ avatar: [
@ -142,7 +142,7 @@ Paginator(
Text("\n"), Text("\n"),
Text("👇"), Text("👇"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCKBVxnCV35xZ9Oe1U6DLENQ", id: "UCKBVxnCV35xZ9Oe1U6DLENQ",
name: "Brian Kenneth", name: "Brian Kenneth",
avatar: [ avatar: [
@ -183,7 +183,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Love this song so much"), Text("Love this song so much"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCsJS5T1NM3Ra7HLmiPjxeGg", id: "UCsJS5T1NM3Ra7HLmiPjxeGg",
name: "milky way", name: "milky way",
avatar: [ avatar: [
@ -224,7 +224,7 @@ Paginator(
text: RichText([ text: RichText([
Text("They are the background of our karaoke"), Text("They are the background of our karaoke"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCh6Qqw1NFPNi6l7kfU1b4PA", id: "UCh6Qqw1NFPNi6l7kfU1b4PA",
name: "ae 💜", name: "ae 💜",
avatar: [ avatar: [
@ -265,7 +265,7 @@ Paginator(
text: RichText([ text: RichText([
Text("AESPA"), Text("AESPA"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCh6Qqw1NFPNi6l7kfU1b4PA", id: "UCh6Qqw1NFPNi6l7kfU1b4PA",
name: "ae 💜", name: "ae 💜",
avatar: [ avatar: [
@ -306,7 +306,7 @@ Paginator(
text: RichText([ text: RichText([
Text("AVATAR EXPERIENCE ASPECT"), Text("AVATAR EXPERIENCE ASPECT"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCh6Qqw1NFPNi6l7kfU1b4PA", id: "UCh6Qqw1NFPNi6l7kfU1b4PA",
name: "ae 💜", name: "ae 💜",
avatar: [ avatar: [
@ -347,7 +347,7 @@ Paginator(
text: RichText([ text: RichText([
Text("HEIHH!!"), Text("HEIHH!!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCgTOQ5KTAurWso9Hw2IGVow", id: "UCgTOQ5KTAurWso9Hw2IGVow",
name: "WinterMyUniverse", name: "WinterMyUniverse",
avatar: [ avatar: [
@ -388,7 +388,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Road to 234M!"), Text("Road to 234M!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCuTNUUpUzXVljMSEy1YooZw", id: "UCuTNUUpUzXVljMSEy1YooZw",
name: "The Ultimate 1", name: "The Ultimate 1",
avatar: [ avatar: [
@ -429,7 +429,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Happy 4m likes!"), Text("Happy 4m likes!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCbfj_QOoelszMm1JlXpY7nw", id: "UCbfj_QOoelszMm1JlXpY7nw",
name: "Sim Layla", name: "Sim Layla",
avatar: [ avatar: [
@ -470,7 +470,7 @@ Paginator(
text: RichText([ text: RichText([
Text("MY\'s and aespa go fighting!"), Text("MY\'s and aespa go fighting!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCh6Qqw1NFPNi6l7kfU1b4PA", id: "UCh6Qqw1NFPNi6l7kfU1b4PA",
name: "ae 💜", name: "ae 💜",
avatar: [ avatar: [
@ -511,7 +511,7 @@ Paginator(
text: RichText([ text: RichText([
Text("I hope they bring back this colorful set for the next comeback"), Text("I hope they bring back this colorful set for the next comeback"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCh6Qqw1NFPNi6l7kfU1b4PA", id: "UCh6Qqw1NFPNi6l7kfU1b4PA",
name: "ae 💜", name: "ae 💜",
avatar: [ avatar: [
@ -552,7 +552,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Keep str3aming MY\'s"), Text("Keep str3aming MY\'s"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCh6Qqw1NFPNi6l7kfU1b4PA", id: "UCh6Qqw1NFPNi6l7kfU1b4PA",
name: "ae 💜", name: "ae 💜",
avatar: [ avatar: [
@ -593,7 +593,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Ji-min-jeong Cross!"), Text("Ji-min-jeong Cross!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCh6Qqw1NFPNi6l7kfU1b4PA", id: "UCh6Qqw1NFPNi6l7kfU1b4PA",
name: "ae 💜", name: "ae 💜",
avatar: [ avatar: [
@ -634,7 +634,7 @@ Paginator(
text: RichText([ text: RichText([
Text("BEST DEBUT EVER !!!"), Text("BEST DEBUT EVER !!!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC-wGUUnJO1gTAw011kCGwfQ", id: "UC-wGUUnJO1gTAw011kCGwfQ",
name: "darkangel", name: "darkangel",
avatar: [ avatar: [
@ -675,7 +675,7 @@ Paginator(
text: RichText([ text: RichText([
Text("เพลงโครตน\u{e48}าเบ\u{e37}\u{e48}อ ด\u{e35}แค\u{e48} cg"), Text("เพลงโครตน\u{e48}าเบ\u{e37}\u{e48}อ ด\u{e35}แค\u{e48} cg"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCE7UmaNfXFkZ8iO8SZnx1_g", id: "UCE7UmaNfXFkZ8iO8SZnx1_g",
name: "Hopi your", name: "Hopi your",
avatar: [ avatar: [
@ -716,7 +716,7 @@ Paginator(
text: RichText([ text: RichText([
Text("233230"), Text("233230"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCTV1SSSkB8Rr9Y5pD1tN8eA", id: "UCTV1SSSkB8Rr9Y5pD1tN8eA",
name: "Agus Sudrajat", name: "Agus Sudrajat",
avatar: [ avatar: [

View file

@ -13,7 +13,7 @@ Paginator(
Text("\n"), Text("\n"),
Text("👇"), Text("👇"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC--QwZHg12dkw8UKw5yB1MQ", id: "UC--QwZHg12dkw8UKw5yB1MQ",
name: "Agalla, Andre", name: "Agalla, Andre",
avatar: [ avatar: [
@ -54,7 +54,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Chicas vamos por los 300M, démosle a todas esas haters chorrillo masivo fulminante de la envidia. Vamos, Mys puede a llegar a ser poderoso si nos unimos. Vamos por los 300M solo nos falta poco para llegar!!!!!!! Vamos Mys, alcemos nuestro teléfonos y brindemos por lo que puede hacer las Mys por Aespa"), Text("Chicas vamos por los 300M, démosle a todas esas haters chorrillo masivo fulminante de la envidia. Vamos, Mys puede a llegar a ser poderoso si nos unimos. Vamos por los 300M solo nos falta poco para llegar!!!!!!! Vamos Mys, alcemos nuestro teléfonos y brindemos por lo que puede hacer las Mys por Aespa"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCqT9iACjb69o254SFlUjcDQ", id: "UCqT9iACjb69o254SFlUjcDQ",
name: "Camila paz", name: "Camila paz",
avatar: [ avatar: [
@ -95,7 +95,7 @@ Paginator(
text: RichText([ text: RichText([
Text("The best 4th gen group debut for me. Camerawork, artistic value, choreography, concept, make up and styling, this one nailed ALL."), Text("The best 4th gen group debut for me. Camerawork, artistic value, choreography, concept, make up and styling, this one nailed ALL."),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC00F5JjCjDDum6MlP3eloxw", id: "UC00F5JjCjDDum6MlP3eloxw",
name: "The Charging Knight of Amarapura", name: "The Charging Knight of Amarapura",
avatar: [ avatar: [
@ -136,7 +136,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Black Manba o MV mais icônico do aespa amooooi"), Text("Black Manba o MV mais icônico do aespa amooooi"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCbfGo61YSYOlfyF1cWejhng", id: "UCbfGo61YSYOlfyF1cWejhng",
name: "Kim Jamily Sun", name: "Kim Jamily Sun",
avatar: [ avatar: [
@ -177,7 +177,7 @@ Paginator(
text: RichText([ text: RichText([
Text("MYs if we want to make Black Mamba the most debut MV for 4th gen- let us keep on strêaming. Consistency is the key."), Text("MYs if we want to make Black Mamba the most debut MV for 4th gen- let us keep on strêaming. Consistency is the key."),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCITMz9SiXQrV-cltI-9Auuw", id: "UCITMz9SiXQrV-cltI-9Auuw",
name: "Stream Girls, Savage, Next Level and Black Mamba", name: "Stream Girls, Savage, Next Level and Black Mamba",
avatar: [ avatar: [
@ -223,7 +223,7 @@ Paginator(
Text("\n"), Text("\n"),
Text("(ps. Winter is my love <3)"), Text("(ps. Winter is my love <3)"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCDaOL1lsanMlpbzaQunz47Q", id: "UCDaOL1lsanMlpbzaQunz47Q",
name: "ehe", name: "ehe",
avatar: [ avatar: [
@ -270,7 +270,7 @@ Paginator(
Text("\n"), Text("\n"),
Text("Forever, Dreams come true --> 50 M"), Text("Forever, Dreams come true --> 50 M"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC2P4Zx1o4D3VQIjA_MIToQQ", id: "UC2P4Zx1o4D3VQIjA_MIToQQ",
name: "edits&fun", name: "edits&fun",
avatar: [ avatar: [
@ -311,7 +311,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Logremos más de 250M Antes de que se termine el año ♡"), Text("Logremos más de 250M Antes de que se termine el año ♡"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC5cxR3XtdfVR_XT3sfIKdNg", id: "UC5cxR3XtdfVR_XT3sfIKdNg",
name: "Black mamba 🐍💜", name: "Black mamba 🐍💜",
avatar: [ avatar: [
@ -352,7 +352,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Llevemos está Masterpiece a los 300M!! ಥ‿ಥ♡ Don\'t stop My, 230M soon"), Text("Llevemos está Masterpiece a los 300M!! ಥ‿ಥ♡ Don\'t stop My, 230M soon"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC5cxR3XtdfVR_XT3sfIKdNg", id: "UC5cxR3XtdfVR_XT3sfIKdNg",
name: "Black mamba 🐍💜", name: "Black mamba 🐍💜",
avatar: [ avatar: [
@ -393,7 +393,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Keep streaming my\'s let\'s reach 300 million views before aespa\'s full album comeback."), Text("Keep streaming my\'s let\'s reach 300 million views before aespa\'s full album comeback."),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCfQOeizIiPTG3hgKa-6MOeA", id: "UCfQOeizIiPTG3hgKa-6MOeA",
name: "K-POP", name: "K-POP",
avatar: [ avatar: [
@ -436,7 +436,7 @@ Paginator(
Text("\n"), Text("\n"),
Text("Vamos que si se puede"), Text("Vamos que si se puede"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCgRWbRJqUHCvWv6xOuB4few", id: "UCgRWbRJqUHCvWv6xOuB4few",
name: "Karina González", name: "Karina González",
avatar: [ avatar: [
@ -477,7 +477,7 @@ Paginator(
text: RichText([ text: RichText([
Text("DENLE LIKE AL MV Q FALTA POCO PARA LOS 4M DE LIKES ¡!¡!¡"), Text("DENLE LIKE AL MV Q FALTA POCO PARA LOS 4M DE LIKES ¡!¡!¡"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCBqR9kJhtiHLE6dP-Oo_DMQ", id: "UCBqR9kJhtiHLE6dP-Oo_DMQ",
name: "yujiminemo", name: "yujiminemo",
avatar: [ avatar: [
@ -518,7 +518,7 @@ Paginator(
text: RichText([ text: RichText([
Text("146 millones vamos por 147 millones si se puede vamos a por mas GO"), Text("146 millones vamos por 147 millones si se puede vamos a por mas GO"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCjbUNOs6PAAAAo3_feDwLQA", id: "UCjbUNOs6PAAAAo3_feDwLQA",
name: "OLIVER79K", name: "OLIVER79K",
avatar: [ avatar: [
@ -559,7 +559,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Best MV debut for this gen!"), Text("Best MV debut for this gen!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCjXq-4-e-OKn1S3SB52wHRQ", id: "UCjXq-4-e-OKn1S3SB52wHRQ",
name: "viclusiv", name: "viclusiv",
avatar: [ avatar: [
@ -600,7 +600,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Ya es 2022 y aún no superó este M/V, stream mys para los 300M!"), Text("Ya es 2022 y aún no superó este M/V, stream mys para los 300M!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCwan9APGANDUfYdYBbU6OeQ", id: "UCwan9APGANDUfYdYBbU6OeQ",
name: "mynlemus", name: "mynlemus",
avatar: [ avatar: [
@ -641,7 +641,7 @@ Paginator(
text: RichText([ text: RichText([
Text("I get goosebump every single time it comes to NingNings high note. Baby youre amazingggg"), Text("I get goosebump every single time it comes to NingNings high note. Baby youre amazingggg"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC3IEDx0AQiUOP8FtC_MlyFQ", id: "UC3IEDx0AQiUOP8FtC_MlyFQ",
name: "Yến Anh", name: "Yến Anh",
avatar: [ avatar: [
@ -682,7 +682,7 @@ Paginator(
text: RichText([ text: RichText([
Text("This is still the best K-pop debut <3 MYS LETS STREAM HARD FOR GIRLS"), Text("This is still the best K-pop debut <3 MYS LETS STREAM HARD FOR GIRLS"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UC2vbH7mtFRTiPGLRt9l_OSw", id: "UC2vbH7mtFRTiPGLRt9l_OSw",
name: "Flavia", name: "Flavia",
avatar: [ avatar: [
@ -723,7 +723,7 @@ Paginator(
text: RichText([ text: RichText([
Text("Don\'t be shy SM Entertainment! Give the girls another legendary comeback!"), Text("Don\'t be shy SM Entertainment! Give the girls another legendary comeback!"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCWgL2cewcYnsIqwN1tMikJg", id: "UCWgL2cewcYnsIqwN1tMikJg",
name: "⇮ æluvieyou ⇮", name: "⇮ æluvieyou ⇮",
avatar: [ avatar: [
@ -764,7 +764,7 @@ Paginator(
text: RichText([ text: RichText([
Text("aespa\'s debut song is really powerful. I\'ve been listening to this song many times since its release. But, the energy the song is sending me is just as powerful"), Text("aespa\'s debut song is really powerful. I\'ve been listening to this song many times since its release. But, the energy the song is sending me is just as powerful"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCN4tkZuSBXlZ5b9E8CETBUw", id: "UCN4tkZuSBXlZ5b9E8CETBUw",
name: "MYSoneluvie", name: "MYSoneluvie",
avatar: [ avatar: [
@ -807,7 +807,7 @@ Paginator(
Text("🔥"), Text("🔥"),
Text("💎"), Text("💎"),
]), ]),
author: Some(Channel( author: Some(ChannelTag(
id: "UCoU9ZmBOV-CB2Mjl_JM3-ZA", id: "UCoU9ZmBOV-CB2Mjl_JM3-ZA",
name: "Melodies_Memory of exy", name: "Melodies_Memory of exy",
avatar: [ avatar: [

View file

@ -21,7 +21,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -55,7 +55,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCYDmx2Sfpnaxg488yBpZIGg", id: "UCYDmx2Sfpnaxg488yBpZIGg",
name: "starshipTV", name: "starshipTV",
avatar: [ avatar: [
@ -89,7 +89,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC_pwIXKXNm5KGhdEVzmY60A", id: "UC_pwIXKXNm5KGhdEVzmY60A",
name: "Stone Music Entertainment", name: "Stone Music Entertainment",
avatar: [ avatar: [
@ -123,7 +123,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCS_hnpJLQTvBkqALgapi_4g", id: "UCS_hnpJLQTvBkqALgapi_4g",
name: "스브스케이팝 X INKIGAYO", name: "스브스케이팝 X INKIGAYO",
avatar: [ avatar: [
@ -157,7 +157,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg", id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa", name: "aespa",
avatar: [ avatar: [
@ -191,7 +191,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -225,7 +225,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -259,7 +259,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A", id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK", name: "BLACKPINK",
avatar: [ avatar: [
@ -293,7 +293,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg", id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa", name: "aespa",
avatar: [ avatar: [
@ -327,7 +327,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCritGVo7pLJLUS8wEu32vow", id: "UCritGVo7pLJLUS8wEu32vow",
name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)", name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)",
avatar: [ avatar: [
@ -361,7 +361,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -395,7 +395,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -429,7 +429,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -463,7 +463,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -497,7 +497,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -531,7 +531,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg", id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa", name: "aespa",
avatar: [ avatar: [
@ -565,7 +565,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A", id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK", name: "BLACKPINK",
avatar: [ avatar: [
@ -599,7 +599,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCuhAUMLzJxlP1W7mEk0_6lA", id: "UCuhAUMLzJxlP1W7mEk0_6lA",
name: "MAMAMOO", name: "MAMAMOO",
avatar: [ avatar: [
@ -633,7 +633,7 @@ Paginator(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [

View file

@ -6,7 +6,7 @@ VideoDetails(
id: "HRKu0cvrr_o", id: "HRKu0cvrr_o",
title: "AlphaOmegaSin Fanboy Logic: Likes/Dislikes Disabled = Point Invalid Lol wtf?", title: "AlphaOmegaSin Fanboy Logic: Likes/Dislikes Disabled = Point Invalid Lol wtf?",
description: RichText([]), description: RichText([]),
channel: Channel( channel: ChannelTag(
id: "UCQT2yul0lr6Ie9qNQNmw-sg", id: "UCQT2yul0lr6Ie9qNQNmw-sg",
name: "PrinceOfFALLEN", name: "PrinceOfFALLEN",
avatar: [ avatar: [

View file

@ -18,7 +18,7 @@ VideoDetails(
Text("\n\n"), Text("\n\n"),
Text("#36C3"), Text("#36C3"),
]), ]),
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -67,7 +67,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -101,7 +101,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCBWSgdr27NcLig0XzWLq2gQ", id: "UCBWSgdr27NcLig0XzWLq2gQ",
name: "MISS-VERSTEHEN SIE MICH RICHTIG", name: "MISS-VERSTEHEN SIE MICH RICHTIG",
avatar: [ avatar: [
@ -135,7 +135,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -169,7 +169,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -203,7 +203,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -237,7 +237,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -271,7 +271,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -305,7 +305,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -339,7 +339,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCvZLsBb-8Og4FvBUom9zPHQ", id: "UCvZLsBb-8Og4FvBUom9zPHQ",
name: "Universität Bayreuth", name: "Universität Bayreuth",
avatar: [ avatar: [
@ -373,7 +373,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -407,7 +407,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -441,7 +441,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -475,7 +475,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCLLibJTCy3sXjHLVaDimnpQ", id: "UCLLibJTCy3sXjHLVaDimnpQ",
name: "ARTEde", name: "ARTEde",
avatar: [ avatar: [
@ -509,7 +509,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -543,7 +543,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -577,7 +577,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -611,7 +611,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [
@ -645,7 +645,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCeO-zvUfuEdPMDoNST6hy1A", id: "UCeO-zvUfuEdPMDoNST6hy1A",
name: "Killuminati ∆", name: "Killuminati ∆",
avatar: [ avatar: [
@ -679,7 +679,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2TXq_t06Hjdr2g_KdKpHQg", id: "UC2TXq_t06Hjdr2g_KdKpHQg",
name: "media.ccc.de", name: "media.ccc.de",
avatar: [ avatar: [

View file

@ -229,7 +229,7 @@ VideoDetails(
), ),
Text(" Conclusion"), Text(" Conclusion"),
]), ]),
channel: Channel( channel: ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw", id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips", name: "Linus Tech Tips",
avatar: [ avatar: [
@ -503,7 +503,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw", id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips", name: "Linus Tech Tips",
avatar: [ avatar: [
@ -537,7 +537,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw", id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips", name: "Linus Tech Tips",
avatar: [ avatar: [
@ -571,7 +571,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCdBK94H6oZT2Q7l0-b0xmMg", id: "UCdBK94H6oZT2Q7l0-b0xmMg",
name: "ShortCircuit", name: "ShortCircuit",
avatar: [ avatar: [
@ -605,7 +605,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC7Jwj9fkrf1adN4fMmTkpug", id: "UC7Jwj9fkrf1adN4fMmTkpug",
name: "DankPods", name: "DankPods",
avatar: [ avatar: [
@ -639,7 +639,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw", id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips", name: "Linus Tech Tips",
avatar: [ avatar: [
@ -673,7 +673,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCKd49wwdEdIoM-7Fumhwmog", id: "UCKd49wwdEdIoM-7Fumhwmog",
name: "Quint BUILDs", name: "Quint BUILDs",
avatar: [ avatar: [
@ -707,7 +707,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEIwxahdLz7bap-VDs9h35A", id: "UCEIwxahdLz7bap-VDs9h35A",
name: "Steve Mould", name: "Steve Mould",
avatar: [ avatar: [
@ -741,7 +741,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCkWQ0gDrqOCarmUKmppD7GQ", id: "UCkWQ0gDrqOCarmUKmppD7GQ",
name: "JayzTwoCents", name: "JayzTwoCents",
avatar: [ avatar: [
@ -775,7 +775,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UChIZGfcnjHI0DG4nweWEduw", id: "UChIZGfcnjHI0DG4nweWEduw",
name: "TechSource", name: "TechSource",
avatar: [ avatar: [
@ -809,7 +809,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVveEFTOd6khhSXXnRhxJmg", id: "UCVveEFTOd6khhSXXnRhxJmg",
name: "Fireball Tool", name: "Fireball Tool",
avatar: [ avatar: [
@ -843,7 +843,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCq1Oqk1I7zeYlDiJTFWLoFA", id: "UCq1Oqk1I7zeYlDiJTFWLoFA",
name: "Electric Classic Cars", name: "Electric Classic Cars",
avatar: [ avatar: [
@ -877,7 +877,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCvJJ_dzjViJCoLf5uKUTwoA", id: "UCvJJ_dzjViJCoLf5uKUTwoA",
name: "CNBC", name: "CNBC",
avatar: [ avatar: [
@ -911,7 +911,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCMiJRAwDNSNzuYeN2uWa0pA", id: "UCMiJRAwDNSNzuYeN2uWa0pA",
name: "Mrwhosetheboss", name: "Mrwhosetheboss",
avatar: [ avatar: [
@ -945,7 +945,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC_SLthyNX_ivd-dmsFgmJVg", id: "UC_SLthyNX_ivd-dmsFgmJVg",
name: "Jeremy Fielding", name: "Jeremy Fielding",
avatar: [ avatar: [
@ -979,7 +979,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw", id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips", name: "Linus Tech Tips",
avatar: [ avatar: [
@ -1013,7 +1013,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCupQghOyPai8Hxg4RqMERvA", id: "UCupQghOyPai8Hxg4RqMERvA",
name: "incT", name: "incT",
avatar: [ avatar: [
@ -1047,7 +1047,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw", id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips", name: "Linus Tech Tips",
avatar: [ avatar: [
@ -1081,7 +1081,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCXuqSBlHAE6Xw-yeJA0Tunw", id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
name: "Linus Tech Tips", name: "Linus Tech Tips",
avatar: [ avatar: [
@ -1115,7 +1115,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCYmna5rFHIesFteksAvFOfg", id: "UCYmna5rFHIesFteksAvFOfg",
name: "Dr. Plants", name: "Dr. Plants",
avatar: [ avatar: [

View file

@ -38,7 +38,7 @@ VideoDetails(
url: "http://incompetech.com/music/royalty-free/", url: "http://incompetech.com/music/royalty-free/",
), ),
]), ]),
channel: Channel( channel: ChannelTag(
id: "UCakgsb0w7QB0VHdnCc-OVEA", id: "UCakgsb0w7QB0VHdnCc-OVEA",
name: "Space Videos", name: "Space Videos",
avatar: [ avatar: [
@ -87,7 +87,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC_sXrcURB-Dh4az_FveeQ0Q", id: "UC_sXrcURB-Dh4az_FveeQ0Q",
name: "DOCUMENTARY TUBE", name: "DOCUMENTARY TUBE",
avatar: [ avatar: [
@ -121,7 +121,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCakgsb0w7QB0VHdnCc-OVEA", id: "UCakgsb0w7QB0VHdnCc-OVEA",
name: "Space Videos", name: "Space Videos",
avatar: [ avatar: [
@ -155,7 +155,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCZepiiyNNbD2XL5sWnJBC_A", id: "UCZepiiyNNbD2XL5sWnJBC_A",
name: "Videotizer", name: "Videotizer",
avatar: [ avatar: [
@ -189,7 +189,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCNrGOnduIS9BXIRmDcHasZA", id: "UCNrGOnduIS9BXIRmDcHasZA",
name: "WorldCam", name: "WorldCam",
avatar: [ avatar: [
@ -223,7 +223,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCelk6aHijZq-GJBBB9YpReA", id: "UCelk6aHijZq-GJBBB9YpReA",
name: "BBC News عربي", name: "BBC News عربي",
avatar: [ avatar: [
@ -257,7 +257,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC_sXrcURB-Dh4az_FveeQ0Q", id: "UC_sXrcURB-Dh4az_FveeQ0Q",
name: "DOCUMENTARY TUBE", name: "DOCUMENTARY TUBE",
avatar: [ avatar: [
@ -291,7 +291,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCj-Xm8j6WBgKY8OG7s9r2vQ", id: "UCj-Xm8j6WBgKY8OG7s9r2vQ",
name: "RailCowGirl", name: "RailCowGirl",
avatar: [ avatar: [
@ -325,7 +325,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCR9sFzaG9Ia_kXJhfxtFMBA", id: "UCR9sFzaG9Ia_kXJhfxtFMBA",
name: "melodysheep", name: "melodysheep",
avatar: [ avatar: [
@ -359,7 +359,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCakgsb0w7QB0VHdnCc-OVEA", id: "UCakgsb0w7QB0VHdnCc-OVEA",
name: "Space Videos", name: "Space Videos",
avatar: [ avatar: [
@ -393,7 +393,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCRI_rCIV69l-PmT3oyD64kw", id: "UCRI_rCIV69l-PmT3oyD64kw",
name: "Afraz Explores", name: "Afraz Explores",
avatar: [ avatar: [
@ -427,7 +427,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCZvxw99l3xDC6BIHb8nJKGg", id: "UCZvxw99l3xDC6BIHb8nJKGg",
name: "ElderFox Documentaries", name: "ElderFox Documentaries",
avatar: [ avatar: [
@ -461,7 +461,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC2ccm1GajfSujz7T18d7cKA", id: "UC2ccm1GajfSujz7T18d7cKA",
name: "BBC Studios", name: "BBC Studios",
avatar: [ avatar: [
@ -495,7 +495,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCyrM5blUZAQoX9UvObdjtig", id: "UCyrM5blUZAQoX9UvObdjtig",
name: "Valdemar Gomes", name: "Valdemar Gomes",
avatar: [ avatar: [
@ -529,7 +529,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCgP30k64HHZ0OY1QkEgS6Pw", id: "UCgP30k64HHZ0OY1QkEgS6Pw",
name: "Waa Sop", name: "Waa Sop",
avatar: [ avatar: [
@ -563,7 +563,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCBuDzfvztEJvNll_w1E9xFw", id: "UCBuDzfvztEJvNll_w1E9xFw",
name: "The Random Theorizer", name: "The Random Theorizer",
avatar: [ avatar: [
@ -597,7 +597,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCIBaDdAbGlFDeS33shmlD0A", id: "UCIBaDdAbGlFDeS33shmlD0A",
name: "European Space Agency, ESA", name: "European Space Agency, ESA",
avatar: [ avatar: [
@ -631,7 +631,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCakgsb0w7QB0VHdnCc-OVEA", id: "UCakgsb0w7QB0VHdnCc-OVEA",
name: "Space Videos", name: "Space Videos",
avatar: [ avatar: [
@ -665,7 +665,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC1znqKFL3jeR0eoA0pHpzvw", id: "UC1znqKFL3jeR0eoA0pHpzvw",
name: "SpaceRip", name: "SpaceRip",
avatar: [ avatar: [
@ -699,7 +699,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC28l88GMXXqZYfY0Ru9h50w", id: "UC28l88GMXXqZYfY0Ru9h50w",
name: "Seán Doran", name: "Seán Doran",
avatar: [ avatar: [
@ -733,7 +733,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCDyeuRnxf_hxEyH1B7aoDQQ", id: "UCDyeuRnxf_hxEyH1B7aoDQQ",
name: "thebhp", name: "thebhp",
avatar: [ avatar: [

View file

@ -8,7 +8,7 @@ VideoDetails(
description: RichText([ description: RichText([
Text("Provided to YouTube by Universal Music Group\n\nGäa · Oonagh\n\nBest Of\n\n℗ An Airforce1 Records / We Love Music recording; ℗ 2014 Universal Music GmbH\n\nReleased on: 2020-08-07\n\nProducer, Associated Performer, Background Vocalist: Hardy Krech\nProducer: Mark Nissen\nAssociated Performer, Background Vocalist: Andreas Fahnert\nAssociated Performer, Background Vocalist: Velile Mchunu\nAssociated Performer, Background Vocalist: Billy King\nAssociated Performer, Background Vocalist: Alex Prince\nAssociated Performer, Flute: Sandro Friedrich\nProgrammer: Hartmut Krech\nEditor: Severin Zahler\nComposer Lyricist: Hartmut Krech\nComposer Lyricist: Mark Nissen\nAuthor: Lukas Hainer\nAuthor: Michael Boden\n\nAuto-generated by YouTube."), Text("Provided to YouTube by Universal Music Group\n\nGäa · Oonagh\n\nBest Of\n\n℗ An Airforce1 Records / We Love Music recording; ℗ 2014 Universal Music GmbH\n\nReleased on: 2020-08-07\n\nProducer, Associated Performer, Background Vocalist: Hardy Krech\nProducer: Mark Nissen\nAssociated Performer, Background Vocalist: Andreas Fahnert\nAssociated Performer, Background Vocalist: Velile Mchunu\nAssociated Performer, Background Vocalist: Billy King\nAssociated Performer, Background Vocalist: Alex Prince\nAssociated Performer, Flute: Sandro Friedrich\nProgrammer: Hartmut Krech\nEditor: Severin Zahler\nComposer Lyricist: Hartmut Krech\nComposer Lyricist: Mark Nissen\nAuthor: Lukas Hainer\nAuthor: Michael Boden\n\nAuto-generated by YouTube."),
]), ]),
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -57,7 +57,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -91,7 +91,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -125,7 +125,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -159,7 +159,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -193,7 +193,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -227,7 +227,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -261,7 +261,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -295,7 +295,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -329,7 +329,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -363,7 +363,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -397,7 +397,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC8mcGChRS6Zm7pCSYbHeoVw", id: "UC8mcGChRS6Zm7pCSYbHeoVw",
name: "princessZelda", name: "princessZelda",
avatar: [ avatar: [
@ -431,7 +431,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -465,7 +465,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [
@ -499,7 +499,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCVGvnqB-5znqPSbMGlhF4Pw", id: "UCVGvnqB-5znqPSbMGlhF4Pw",
name: "Sentamusic", name: "Sentamusic",
avatar: [ avatar: [

View file

@ -69,7 +69,7 @@ VideoDetails(
Text("#에스파"), Text("#에스파"),
Text("\naespa 에스파 \'Black Mamba\' MV ℗ SM Entertainment"), Text("\naespa 에스파 \'Black Mamba\' MV ℗ SM Entertainment"),
]), ]),
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -118,7 +118,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -152,7 +152,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -186,7 +186,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC_pwIXKXNm5KGhdEVzmY60A", id: "UC_pwIXKXNm5KGhdEVzmY60A",
name: "Stone Music Entertainment", name: "Stone Music Entertainment",
avatar: [ avatar: [
@ -220,7 +220,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCuhAUMLzJxlP1W7mEk0_6lA", id: "UCuhAUMLzJxlP1W7mEk0_6lA",
name: "MAMAMOO", name: "MAMAMOO",
avatar: [ avatar: [
@ -254,7 +254,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCritGVo7pLJLUS8wEu32vow", id: "UCritGVo7pLJLUS8wEu32vow",
name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)", name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)",
avatar: [ avatar: [
@ -288,7 +288,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -322,7 +322,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -356,7 +356,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -390,7 +390,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -424,7 +424,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -458,7 +458,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -492,7 +492,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A", id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK", name: "BLACKPINK",
avatar: [ avatar: [
@ -526,7 +526,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -560,7 +560,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A", id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK", name: "BLACKPINK",
avatar: [ avatar: [
@ -594,7 +594,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -628,7 +628,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCYDmx2Sfpnaxg488yBpZIGg", id: "UCYDmx2Sfpnaxg488yBpZIGg",
name: "starshipTV", name: "starshipTV",
avatar: [ avatar: [
@ -662,7 +662,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCK8S6QMrTk1G8TYQwIyDo-w", id: "UCK8S6QMrTk1G8TYQwIyDo-w",
name: "𝙇𝙌 𝙆𝙋𝙊𝙋", name: "𝙇𝙌 𝙆𝙋𝙊𝙋",
avatar: [ avatar: [
@ -696,7 +696,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg", id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa", name: "aespa",
avatar: [ avatar: [

View file

@ -69,7 +69,7 @@ VideoDetails(
Text("#에스파"), Text("#에스파"),
Text("\naespa 에스파 \'Black Mamba\' MV ℗ SM Entertainment"), Text("\naespa 에스파 \'Black Mamba\' MV ℗ SM Entertainment"),
]), ]),
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -118,7 +118,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCQYl87Oi9aWzz-CLhTw3Rzg", id: "UCQYl87Oi9aWzz-CLhTw3Rzg",
name: "Allan Nascimento", name: "Allan Nascimento",
avatar: [ avatar: [
@ -152,7 +152,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCgqMjKxRWAKUvgYqgomighw", id: "UCgqMjKxRWAKUvgYqgomighw",
name: "KBS충북", name: "KBS충북",
avatar: [ avatar: [
@ -186,7 +186,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCweOkPb1wVVH0Q0Tlj4a5Pw", id: "UCweOkPb1wVVH0Q0Tlj4a5Pw",
name: "1theK (원더케이)", name: "1theK (원더케이)",
avatar: [ avatar: [
@ -220,7 +220,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCqECaJ8Gagnn7YCbPEzWH6g", id: "UCqECaJ8Gagnn7YCbPEzWH6g",
name: "Taylor Swift", name: "Taylor Swift",
avatar: [ avatar: [
@ -254,7 +254,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCweOkPb1wVVH0Q0Tlj4a5Pw", id: "UCweOkPb1wVVH0Q0Tlj4a5Pw",
name: "1theK (원더케이)", name: "1theK (원더케이)",
avatar: [ avatar: [
@ -288,7 +288,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -322,7 +322,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -356,7 +356,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -390,7 +390,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCK8S6QMrTk1G8TYQwIyDo-w", id: "UCK8S6QMrTk1G8TYQwIyDo-w",
name: "LQ K-POP", name: "LQ K-POP",
avatar: [ avatar: [
@ -424,7 +424,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCYvmuw-JtVrTZQ-7Y4kd63Q", id: "UCYvmuw-JtVrTZQ-7Y4kd63Q",
name: "Katy Perry", name: "Katy Perry",
avatar: [ avatar: [
@ -458,7 +458,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A", id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK", name: "BLACKPINK",
avatar: [ avatar: [
@ -492,7 +492,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCaO6TYtlC8U5ttz62hTrZgg", id: "UCaO6TYtlC8U5ttz62hTrZgg",
name: "JYP Entertainment", name: "JYP Entertainment",
avatar: [ avatar: [
@ -526,7 +526,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCOmHUn--16B90oW2L6FRR3A", id: "UCOmHUn--16B90oW2L6FRR3A",
name: "BLACKPINK", name: "BLACKPINK",
avatar: [ avatar: [
@ -560,7 +560,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UC9GtSLeksfK4yuJ_g1lgQbg", id: "UC9GtSLeksfK4yuJ_g1lgQbg",
name: "aespa", name: "aespa",
avatar: [ avatar: [
@ -594,7 +594,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCritGVo7pLJLUS8wEu32vow", id: "UCritGVo7pLJLUS8wEu32vow",
name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)", name: "(G)I-DLE (여자)아이들 (Official YouTube Channel)",
avatar: [ avatar: [
@ -628,7 +628,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCEf_Bc-KVd7onSeifS3py9g", id: "UCEf_Bc-KVd7onSeifS3py9g",
name: "SMTOWN", name: "SMTOWN",
avatar: [ avatar: [
@ -662,7 +662,7 @@ VideoDetails(
height: 188, height: 188,
), ),
], ],
channel: Channel( channel: ChannelTag(
id: "UCk9GmdlDTBfgGRb7vXeRMoQ", id: "UCk9GmdlDTBfgGRb7vXeRMoQ",
name: "Red Velvet", name: "Red Velvet",
avatar: [ avatar: [

View file

@ -6,7 +6,8 @@ use serde::Serialize;
use crate::{ use crate::{
model::{ model::{
Channel, ChannelId, Chapter, Comment, Language, Paginator, RecommendedVideo, VideoDetails, ChannelId, ChannelTag, Chapter, Comment, Language, Paginator, RecommendedVideo,
VideoDetails,
}, },
serializer::MapResult, serializer::MapResult,
timeago, timeago,
@ -302,7 +303,7 @@ impl MapResponse<VideoDetails> for response::VideoDetails {
id: video_id, id: video_id,
title, title,
description, description,
channel: Channel { channel: ChannelTag {
id: channel_id, id: channel_id,
name: channel_name, name: channel_name,
avatar: owner.thumbnail.into(), avatar: owner.thumbnail.into(),
@ -432,7 +433,7 @@ fn map_recommendations(
util::parse_video_length_or_warn(&txt, &mut warnings) util::parse_video_length_or_warn(&txt, &mut warnings)
}), }),
thumbnail: video.thumbnail.into(), thumbnail: video.thumbnail.into(),
channel: Channel { channel: ChannelTag {
id: channel.id, id: channel.id,
name: channel.name, name: channel.name,
avatar: video.channel_thumbnail.into(), avatar: video.channel_thumbnail.into(),
@ -511,7 +512,7 @@ fn map_comment(
id: c.comment_id, id: c.comment_id,
text: c.content_text.into(), text: c.content_text.into(),
author: match (c.author_endpoint, c.author_text) { author: match (c.author_endpoint, c.author_text) {
(Some(aep), Some(name)) => Some(Channel { (Some(aep), Some(name)) => Some(ChannelTag {
id: aep.browse_endpoint.browse_id, id: aep.browse_endpoint.browse_id,
name, name,
avatar: c.author_thumbnail.into(), avatar: c.author_thumbnail.into(),

View file

@ -1,11 +1,13 @@
pub mod locale; pub mod locale;
mod ordering; mod ordering;
mod paginator; mod paginator;
mod param;
pub mod richtext; pub mod richtext;
pub mod stream_filter; pub mod stream_filter;
pub use locale::{Country, Language}; pub use locale::{Country, Language};
pub use paginator::Paginator; pub use paginator::Paginator;
pub use param::ChannelOrder;
use std::ops::Range; use std::ops::Range;
@ -233,7 +235,7 @@ pub struct VideoDetails {
/// Video description /// Video description
pub description: RichText, pub description: RichText,
/// Channel of the video /// Channel of the video
pub channel: Channel, pub channel: ChannelTag,
/// Number of views / current viewers in case of a livestream. /// Number of views / current viewers in case of a livestream.
pub view_count: u64, pub view_count: u64,
/// Number of likes /// Number of likes
@ -299,7 +301,7 @@ pub struct RecommendedVideo {
/// Video thumbnail /// Video thumbnail
pub thumbnail: Vec<Thumbnail>, pub thumbnail: Vec<Thumbnail>,
/// Channel of the video /// Channel of the video
pub channel: Channel, pub channel: ChannelTag,
/// Video publishing date. /// Video publishing date.
/// ///
/// `None` if the date could not be parsed. /// `None` if the date could not be parsed.
@ -318,7 +320,7 @@ pub struct RecommendedVideo {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive] #[non_exhaustive]
pub struct Channel { pub struct ChannelTag {
/// Unique YouTube channel ID /// Unique YouTube channel ID
pub id: String, pub id: String,
/// Channel name /// Channel name
@ -368,7 +370,7 @@ pub struct Comment {
/// Comment author /// Comment author
/// ///
/// There may be comments with missing authors (possibly deleted users?). /// There may be comments with missing authors (possibly deleted users?).
pub author: Option<Channel>, pub author: Option<ChannelTag>,
/// Comment publishing date. /// Comment publishing date.
/// ///
/// `None` if the date could not be parsed. /// `None` if the date could not be parsed.
@ -395,7 +397,7 @@ pub struct Comment {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive] #[non_exhaustive]
pub struct ChannelVideos { pub struct Channel<T> {
/// Unique YouTube Channel-ID (e.g. `UC-lHJZR3Gqxm24_Vd_AJ5Yw`) /// Unique YouTube Channel-ID (e.g. `UC-lHJZR3Gqxm24_Vd_AJ5Yw`)
pub id: String, pub id: String,
/// Channel name /// Channel name
@ -405,8 +407,23 @@ pub struct ChannelVideos {
/// `None` if the subscriber count was hidden by the owner /// `None` if the subscriber count was hidden by the owner
/// or could not be parsed. /// or could not be parsed.
pub subscriber_count: Option<u64>, pub subscriber_count: Option<u64>,
/// Videos fetched from the channel /// Channel avatar / profile picture
pub videos: Paginator<ChannelVideo>, pub avatar: Vec<Thumbnail>,
/// Channel description text
pub description: String,
/// List of words to describe the topic of the channel
pub tags: Vec<String>,
/// Custom URL set by the channel owner
/// (e.g. <https://www.youtube.com/c/EevblogDave>)
pub vanity_url: Option<String>,
/// Banner image shown above the channel
pub banner: Vec<Thumbnail>,
/// Banner image shown above the channel (small format for mobile)
pub mobile_banner: Vec<Thumbnail>,
/// Banner image shown above the channel (16:9 fullscreen format for TV)
pub tv_banner: Vec<Thumbnail>,
/// Content fetched from the channel
pub content: T,
} }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
@ -439,3 +456,27 @@ pub struct ChannelVideo {
/// Is the video a YouTube Short video (vertical and <60s)? /// Is the video a YouTube Short video (vertical and <60s)?
pub is_short: bool, pub is_short: bool,
} }
#[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<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct ChannelInfo {
/// Channel creation date
pub create_date: Option<DateTime<Local>>,
/// Channel view count
pub view_count: Option<u64>,
/// Links to other websites or social media profiles
pub links: Vec<(String, String)>,
}

11
src/model/param.rs Normal file
View file

@ -0,0 +1,11 @@
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ChannelOrder {
/// Output the latest videos first
#[default]
Latest,
/// Output the oldest videos first
Oldest,
/// Output the most viewed videos first
Popular,
}

View file

@ -41,6 +41,25 @@ where
} }
} }
impl<T> MapResult<T>
where
T: Default,
{
pub fn error(msg: String) -> Self {
Self {
c: T::default(),
warnings: vec![msg],
}
}
pub fn ok(c: T) -> Self {
Self {
c,
warnings: Vec::new(),
}
}
}
/// Deserialization method that consumes anything and returns an empty value. /// Deserialization method that consumes anything and returns an empty value.
/// Intended to be used for a wildcard enum option. /// Intended to be used for a wildcard enum option.
/// ///

View file

@ -225,8 +225,10 @@ pub enum PageType {
Playlist, Playlist,
} }
fn map_richtext_run(run: RichTextRun) -> TextComponent { impl From<RichTextRun> for TextComponent {
map_text_component(run.text, run.navigation_endpoint) fn from(run: RichTextRun) -> Self {
map_text_component(run.text, run.navigation_endpoint)
}
} }
/// Map a single component of a rich text /// Map a single component of a rich text
@ -270,7 +272,7 @@ impl<'de> Deserialize<'de> for TextComponent {
)); ));
} }
Ok(map_richtext_run(text.runs.swap_remove(0))) Ok(text.runs.swap_remove(0).into())
} }
} }
@ -280,7 +282,9 @@ impl<'de> Deserialize<'de> for TextComponents {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let text = RichTextInternal::deserialize(deserializer)?; let text = RichTextInternal::deserialize(deserializer)?;
Ok(Self(text.runs.into_iter().map(map_richtext_run).collect())) Ok(Self(
text.runs.into_iter().map(TextComponent::from).collect(),
))
} }
} }
@ -295,7 +299,7 @@ impl<'de> DeserializeAs<'de, TextComponents> for AttributedText {
let mut chars = text.content.chars(); let mut chars = text.content.chars();
// Take a string from the char iterator until the given // Take a string from the char iterator until the given
// UTF-16 index. This mimicks the Javascript substring behavior. // UTF-16 index. This mimics the Javascript substring behavior.
let mut take_chars = |until: usize| { let mut take_chars = |until: usize| {
if until <= i_utf16 { if until <= i_utf16 {
return String::new(); return String::new();
@ -338,7 +342,7 @@ impl<'de> DeserializeAs<'de, TextComponents> for AttributedText {
let txt_link = txt_link.trim(); let txt_link = txt_link.trim();
let txt_link = txt_link.replace("\u{a0}", " "); let txt_link = txt_link.replace("\u{a0}", " ");
static LINK_PREFIX: Lazy<Regex> = Lazy::new(|| Regex::new(r#"^(?:\/|•) *"#).unwrap()); static LINK_PREFIX: Lazy<Regex> = Lazy::new(|| Regex::new("^[/•] *").unwrap());
let txt_link = LINK_PREFIX.replace(&txt_link, ""); let txt_link = LINK_PREFIX.replace(&txt_link, "");
if !txt_before.is_empty() { if !txt_before.is_empty() {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff