1use serde_json::Value;
2use structs::{Album, Artist, Error, Page, Playlist, Search, Song};
3
4use crate::extractors::Fast;
5
6mod extractors;
7mod scrapers;
8pub mod structs;
9
10mod tests;
11
12impl Search {
13 pub async fn fetch(&mut self, page: Page) -> Result<Search, Error> {
14 log::debug!(
15 "SEARCH | Fetching for {} on {:?} page ",
16 self.query.clone(),
17 page.clone(),
18 );
19 let data: Value;
20 match self.get_continuation(page.clone()) {
22 Some(next_page) => {
23 log::debug!("SEARCH | Not new search, has history about this page");
24
25 let specific_search =
27 scrapers::youtube::search(structs::YtSearchType::Final(next_page)).await;
28
29 let next_page = extractors::youtube::search::cont::extract_from_contiunation_search(
32 specific_search.as_ref().unwrap().clone(),
33 );
34
35 match next_page {
36 Err(error) => {
37 log::warn!(
38 "Hmm.. there seems to be no next page for this kind of search {:?} or the extractor might be broken ({:?})",
39 page,
40 error
41 )
42 }
43 Ok(next_page) => self.set_continuation(next_page, page.clone()),
44 }
45 data = specific_search.unwrap()["continuationContents"]["musicShelfContinuation"]
46 ["contents"]
47 .clone();
48 }
49 None => {
50 log::debug!("SEARCH | New search, no history");
51 let generic_search =
53 scrapers::youtube::search(structs::YtSearchType::Basic(self.query.clone()))
54 .await;
55
56 let cont = extractors::youtube::search::cont::extract_from_basic_search(
57 generic_search.unwrap(),
58 page.clone(),
59 );
60
61 let specific_search = scrapers::youtube::search(
63 structs::YtSearchType::Continuation(self.query.clone(), cont.unwrap()),
64 )
65 .await;
66
67 let next_page = extractors::youtube::search::cont::extract_from_specific_search(
69 specific_search.as_ref().unwrap().clone(),
70 );
71 match next_page {
72 Err(_) => {
73 log::warn!(
74 "Hmm.. there seems to be no next page for this kind of search {:?}",
75 page
76 )
77 }
78 Ok(next_page) => self.set_continuation(next_page, page.clone()),
79 }
80
81 match specific_search.unwrap().pointer_converter("/contents/tabbedSearchResultsRenderer/tabs/0/tabRenderer/content/sectionListRenderer/contents/1/musicShelfRenderer/contents"){
82 Ok(items) => data = items,
83 Err(error) => return Err(error)
84 };
85 }
86 }
87
88 match page {
89 Page::Song => return extractors::youtube::search::song::extract(data.clone(), self),
90 Page::Artist => {
91 return extractors::youtube::search::artist::extract(data.clone(), self)
92 }
93 Page::Album => return extractors::youtube::search::album::extract(data.clone(), self),
94 Page::Playlist => {
95 return extractors::youtube::search::playlist::extract(data.clone(), self)
96 }
97 }
98 }
99}
100
101impl Song {
102 pub async fn fetch(&mut self) -> Result<Song, Error> {
103 match scrapers::youtube::song(self.id.clone()).await {
104 Ok(song_value) => match extractors::youtube::normal::song::extract(song_value) {
105 Ok(song) => {
106 *self = song.clone();
107 return Ok(song);
108 }
109 Err(error) => return Err(error),
110 },
111 Err(error) => {
112 return Err(error);
113 }
114 }
115 }
116}
117impl Artist {
118 pub async fn fetch(&mut self) -> Result<Artist, Error> {
119 match scrapers::youtube::browse(self.id.clone()).await {
120 Ok(artist) => match extractors::youtube::normal::artist::extract(artist) {
121 Ok(artist) => {
122 *self = artist.clone();
123 return Ok(artist);
124 }
125 Err(error) => return Err(error),
126 },
127 Err(error) => {
128 return Err(error);
129 }
130 }
131 }
132}
133
134impl Playlist {
136 pub async fn fetch(&mut self) -> Result<Playlist, Error> {
137 match scrapers::youtube::browse(self.id.clone()).await {
138 Ok(playlist) => match extractors::youtube::normal::playlist::extract(playlist) {
139 Ok(playlist) => {
140 *self = playlist.clone();
141 return Ok(playlist);
142 }
143 Err(error) => return Err(error),
144 },
145 Err(error) => {
146 return Err(error);
147 }
148 }
149 }
150}
151impl Album {
152 pub async fn fetch(&mut self) -> Result<Album, Error> {
153 match scrapers::youtube::browse(self.id.clone()).await {
154 Ok(playlist) => match extractors::youtube::normal::album::extract(playlist) {
155 Ok(album) => {
156 *self = album.clone();
157 return Ok(album);
158 }
159 Err(error) => return Err(error),
160 },
161 Err(error) => {
162 return Err(error);
163 }
164 }
165 }
166}