use crate::youtube::{
self,
next::{
CompactMovieRenderer, CompactPlaylistRenderer, CompactRadioRenderer, CompactVideoRenderer,
},
parse_length,
};
use std::fmt::Debug;
#[derive(Clone)]
pub struct Video(pub(super) CompactVideoRenderer, pub(super) crate::Client);
impl Video {
pub fn id(&self) -> super::Id {
self.0.video_id
}
pub fn title(&self) -> &str {
&self.0.title
}
pub fn thumbnails(&self) -> impl Iterator<Item = &crate::Thumbnail> {
self.0.thumbnail.thumbnails.iter()
}
pub fn views(&self) -> Option<u64> {
let s: &str = match self.0.view_count_text.as_ref()? {
crate::youtube::Text::SimpleText(simple) => {
simple
.simple_text
.split_once(' ')
.expect("No space in view_count_text")
.0
}
crate::youtube::Text::Runs(runs) => &runs.runs[0].text,
};
Some(s.replace(',', "").parse().expect("Views were not parsable"))
}
pub fn length(&self) -> Option<std::time::Duration> {
self.0.length_text.as_deref().map(parse_length)
}
pub fn channel(&self) -> Channel<'_> {
Channel {
id: Some(
self.0.short_byline_text.runs[0]
.navigation_endpoint
.browse_endpoint
.browse_id,
),
name: &self.0.short_byline_text.runs[0].text,
badges: &self.0.owner_badges,
client: &self.1,
}
}
pub async fn upgrade(&self) -> crate::Result<crate::Video> {
self.1.video(self.id()).await
}
pub async fn streams(&self) -> crate::Result<impl Iterator<Item = crate::Stream>> {
self.1.streams(self.id()).await
}
}
impl std::fmt::Debug for Video {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Video")
.field("id", &self.id())
.field("title", &self.title())
.field("thumbnails", &self.thumbnails().collect::<Vec<_>>())
.field("views", &self.views())
.field("length", &self.length())
.field("channel", &self.channel())
.finish()
}
}
impl PartialEq for Video {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl Eq for Video {}
#[derive(Clone)]
pub struct Playlist(pub(super) CompactPlaylistRenderer, pub(super) crate::Client);
impl Playlist {
pub fn id(&self) -> crate::playlist::Id {
crate::playlist::Id(self.0.playlist_id.clone())
}
pub fn title(&self) -> &str {
&self.0.title
}
pub fn thumbnails(&self) -> impl Iterator<Item = &crate::Thumbnail> {
self.0.thumbnail.thumbnails.iter()
}
pub fn channel(&self) -> Channel<'_> {
Channel {
id: self.0.channel_id(),
name: &self.0.channel_name(),
badges: &self.0.owner_badges,
client: &self.1,
}
}
pub async fn upgrade(&self) -> crate::Result<crate::Playlist> {
self.1.playlist(self.id()).await
}
}
impl Debug for Playlist {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Playlist")
.field("id", &self.id())
.field("title", &self.title())
.field("thumbnails", &self.thumbnails().collect::<Vec<_>>())
.field("channel", &self.channel())
.finish()
}
}
impl PartialEq for Playlist {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl Eq for Playlist {}
#[derive(Clone)]
pub struct Radio(pub(super) CompactRadioRenderer, pub(super) crate::Client);
impl Radio {
pub fn id(&self) -> crate::playlist::Id {
crate::playlist::Id(self.0.playlist_id.clone())
}
pub fn title(&self) -> &str {
&self.0.title
}
pub fn thumbnails(&self) -> impl Iterator<Item = &crate::Thumbnail> {
self.0.thumbnail.thumbnails.iter()
}
pub async fn upgrade(&self) -> crate::Result<crate::Playlist> {
self.1.playlist(self.id()).await
}
}
impl Debug for Radio {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Radio")
.field("id", &self.id())
.field("title", &self.title())
.field("thumbnails", &self.thumbnails().collect::<Vec<_>>())
.finish()
}
}
impl PartialEq for Radio {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl Eq for Radio {}
#[derive(Clone)]
pub struct Movie(pub(super) CompactMovieRenderer, pub(super) crate::Client);
impl Movie {
pub fn id(&self) -> super::Id {
self.0.video_id
}
pub fn title(&self) -> &str {
&self.0.title
}
pub fn thumbnails(&self) -> impl Iterator<Item = &crate::Thumbnail> {
self.0.thumbnail.thumbnails.iter()
}
pub fn length(&self) -> std::time::Duration {
parse_length(&self.0.length_text)
}
pub async fn upgrade(&self) -> crate::Result<crate::Video> {
self.1.video(self.id()).await
}
}
impl std::fmt::Debug for Movie {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Movie")
.field("id", &self.id())
.field("title", &self.title())
.field("thumbnails", &self.thumbnails().collect::<Vec<_>>())
.field("length", &self.length())
.finish()
}
}
impl PartialEq for Movie {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl Eq for Movie {}
#[derive(Clone)]
pub struct Channel<'a> {
id: Option<crate::channel::Id>,
name: &'a str,
badges: &'a Vec<youtube::Badge>,
client: &'a crate::Client,
}
impl<'a> Channel<'a> {
pub fn id(&self) -> Option<crate::channel::Id> {
self.id
}
pub fn name(&self) -> &str {
self.name
}
pub fn badges(&self) -> impl Iterator<Item = crate::channel::Badge> + '_ {
self.badges.iter().map(crate::channel::Badge::from)
}
pub async fn upgrade(&self) -> Option<crate::Result<crate::Channel>> {
Some(self.client.channel(self.id?).await)
}
}
impl<'a> std::fmt::Debug for Channel<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Channel")
.field("id", &self.id())
.field("name", &self.name())
.field("badges", &self.badges().collect::<Vec<_>>())
.finish()
}
}
impl<'a> PartialEq for Channel<'a> {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl<'a> Eq for Channel<'a> {}