use serde::Deserialize; #[derive(Deserialize)] pub struct YoutubeChannel { pub contents: ChannelContents, } #[derive(Deserialize)] pub struct ChannelContents { pub twoColumnBrowseResultsRenderer: TwoColumns, } #[derive(Deserialize)] pub struct TwoColumns { pub tabs: Vec } #[derive(Deserialize)] pub struct ChannelTab { pub tabRenderer: Option } #[derive(Deserialize)] pub struct TabRenderer { pub title: String, pub endpoint: TabEndpoint, pub content: Option } #[derive(Deserialize)] pub struct SectionListRenderer{ pub contents: Option> } #[derive(Deserialize)] pub struct Content { pub itemSectionRenderer: Option } #[derive(Deserialize)] pub struct ItemSectionRenderer { pub contents: Vec } #[derive(Deserialize)] pub struct ItemSectionContent { pub gridRenderer: GridRenderer } #[derive(Deserialize)] pub struct GridRenderer { pub items: Vec } #[derive(Deserialize)] pub struct GridItem { pub lockupViewModel: LookUpViewModel } #[derive(Deserialize)] pub struct LookUpViewModel { pub metadata: ModelMetadata } #[derive(Deserialize)] pub struct ModelMetadata { pub lockupMetadataViewModel: LockupMetadataViewModel } #[derive(Deserialize)] pub struct LockupMetadataViewModel { pub title: PlaylistTitle, pub metadata: PlaylistMetadata, } #[derive(Deserialize)] pub struct PlaylistMetadata { pub contentMetadataViewModel: ContentMetadataViewModel } #[derive(Deserialize)] pub struct ContentMetadataViewModel { pub metadataRows: Vec } #[derive(Deserialize)] pub struct MetadataRow { pub metadataParts: Vec } #[derive(Deserialize, Debug)] pub struct PlaylistTitle { pub content: Option, pub commandRuns: Option>, } #[derive(Deserialize, Debug)] pub struct CommandRun { onTap: OnTap } #[derive(Deserialize, Debug)] pub struct OnTap { innertubeCommand: InnertubeCommand } #[derive(Deserialize, Debug)] pub struct InnertubeCommand { pub browseEndpoint: BrowseEndpoint, } #[derive(Deserialize)] pub struct TabContent { pub sectionListRenderer: SectionListRenderer } #[derive(Deserialize)] pub struct TabEndpoint { pub browseEndpoint: BrowseEndpoint, } #[derive(Deserialize, Debug)] pub struct BrowseEndpoint { pub browseId: String, pub params: Option, } impl YoutubeChannel { pub fn get_playlists_request_str(&self) -> Option { for tab in &self.contents.twoColumnBrowseResultsRenderer.tabs { if let Some(t) = &tab.tabRenderer { if t.title == String::from("Playlists") { return Some(t.endpoint.browseEndpoint.params.as_ref().unwrap().clone()); } } } None } pub fn get_playlists(&self) -> Vec<(String, String)> { let mut arr = Vec::new(); for tab in &self.contents.twoColumnBrowseResultsRenderer.tabs { if let Some(t) = &tab.tabRenderer { if t.title == String::from("Playlists") { for item in &t.content.as_ref().unwrap().sectionListRenderer.contents.as_ref().unwrap()[0].itemSectionRenderer.as_ref().unwrap().contents[0].gridRenderer.items { let title = item.lockupViewModel.metadata.lockupMetadataViewModel.title.content.clone().unwrap_or("!".to_string()); println!("{:#?}", item.lockupViewModel.metadata.lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows[1].metadataParts[0]); let url = item.lockupViewModel.metadata.lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows[1].metadataParts[0].commandRuns.as_ref().unwrap()[0].onTap.innertubeCommand.browseEndpoint.browseId.clone(); arr.push((title, url)); } } } } arr } }