1use std::collections::HashMap;
5use tinyjson::JsonValue;
6
7
8#[allow(dead_code)]
11#[derive(Debug)]
12pub struct ChannelData {
13 pub id: String,
14 pub title: String,
15 pub url: String,
16 pub snippet: String,
17 pub thumbnail_src: String,
18 pub video_count: String,
19 pub subscriber_count: String,
20 pub verified: bool,
21}
22
23#[allow(dead_code)]
26#[derive(Debug)]
27pub struct VideoData {
28 pub id: String,
29 pub title: String,
30 pub url: String,
31 pub duration: String,
32 pub snippet: String,
33 pub upload_date: String,
34 pub thumbnail_src: String,
35 pub views: String,
36}
37#[allow(dead_code)]
40#[derive(Debug)]
41pub struct PlaylistData {
42 pub id: String,
43 pub title: String,
44 pub url: String,
45 pub thumbnail_src: String,
46 pub video_count: String,
47}
48#[allow(dead_code)]
51#[derive(Debug)]
52pub struct VideoUploaderData {
53 pub username: String,
54 pub url: String,
55 pub verified: bool,
56}
57#[allow(dead_code)]
60#[derive(Debug)]
61pub struct PlaylistUploaderData {
62 pub username: String,
63 pub url: String,
64}
65#[derive(Debug)]
68pub enum Item {
69 Channel(ChannelData),
71 Video(VideoData, VideoUploaderData),
73 Playlist(PlaylistData, PlaylistUploaderData),
75 Unknown,
77}
78pub fn raw_search_with_title(query: &str, page: u8) -> Result<JsonValue, Box<dyn std::error::Error>> {
85 let resp = reqwest::blocking::get(format!(
86 "http://youtube-scrape.herokuapp.com/api/search?q={}&page={}",
87 query, page.to_string()
88 ))?;
89 let text = resp.text()?;
90 let parsed: JsonValue = text.parse().unwrap();
91 Ok(parsed)
92}
93
94pub fn get_data(query: &str, page: u8) -> Vec<Item> {
95 let resp = raw_search_with_title(query, page).expect("Error fetching data");
96 let items: &Vec<_> = &resp["results"].get().expect("Error parsing data");
97 let mut data: Vec<Item> = Vec::new();
98
99 for item in items {
100 let simplified: &HashMap<String, JsonValue> =
101 item.get().expect("Error while unpacking data");
102 if simplified.contains_key("channel") {
103 let channel = ChannelData {
104 id: item["channel"]["id"]
105 .get::<String>()
106 .expect("Error while unpacking channel id")
107 .clone(),
108 title: item["channel"]["title"]
109 .get::<String>()
110 .expect("Error while unpacking channel name")
111 .clone(),
112 url: item["channel"]["url"]
113 .get::<String>()
114 .expect("Error while unpacking channel url")
115 .clone(),
116 snippet: item["channel"]["snippet"]
117 .get::<String>()
118 .expect("Error while unpacking snippet")
119 .clone(),
120 thumbnail_src: item["channel"]["thumbnail_src"]
121 .get::<String>()
122 .expect("Error while unpacking thumbnail url")
123 .clone(),
124 video_count: item["channel"]["video_count"]
125 .get::<String>()
126 .expect("Error while unpacking video count")
127 .clone(),
128 subscriber_count: item["channel"]["subscriber_count"]
129 .get::<String>()
130 .expect("Error while unpacking subscriber count")
131 .clone(),
132 verified: match item["channel"]["verified"] {
133 JsonValue::Boolean(v) => v,
134 _ => panic!("Error while unpacking channel verification status"),
135 },
136 };
137 data.push(Item::Channel(channel));
138 } else if simplified.contains_key("video") {
139 let video = VideoData {
140 id: item["video"]["id"]
141 .get::<String>()
142 .expect("Error while unpacking video id")
143 .clone(),
144 title: item["video"]["title"]
145 .get::<String>()
146 .expect("Error while unpacking video title")
147 .clone(),
148 url: item["video"]["url"]
149 .get::<String>()
150 .expect("Error while unpacking video url")
151 .clone(),
152 duration: item["video"]["duration"]
153 .get::<String>()
154 .expect("Error while unpacking video duration")
155 .clone(),
156 upload_date: item["video"]["upload_date"]
157 .get::<String>()
158 .expect("Error while unpacking video upload date")
159 .clone(),
160 snippet: item["video"]["snippet"]
161 .get::<String>()
162 .expect("Error while unpacking snippet")
163 .clone(),
164 thumbnail_src: item["video"]["thumbnail_src"]
165 .get::<String>()
166 .expect("Error while unpacking thumbnail url")
167 .clone(),
168 views: item["video"]["views"]
169 .get::<String>()
170 .expect("Error while unpacking channel url")
171 .clone(),
172 };
173 let uploader = VideoUploaderData {
174 username: item["uploader"]["username"]
175 .get::<String>()
176 .expect("Error while unpacking channel url")
177 .clone(),
178 url: item["uploader"]["url"]
179 .get::<String>()
180 .expect("Error while unpacking channel url")
181 .clone(),
182 verified: match item["uploader"]["verified"] {
183 JsonValue::Boolean(v) => v,
184 _ => panic!("Error while unpacking channel verification status"),
185 },
186 };
187 data.push(Item::Video(video, uploader));
188 } else if simplified.contains_key("playlist") {
189 let playlist = PlaylistData {
190 id: item["playlist"]["id"]
191 .get::<String>()
192 .expect("Error while unpacking playlist id")
193 .clone(),
194 title: item["playlist"]["title"]
195 .get::<String>()
196 .expect("Error while unpacking playlist title")
197 .clone(),
198 url: item["playlist"]["url"]
199 .get::<String>()
200 .expect("Error while unpacking playlist url")
201 .clone(),
202 thumbnail_src: item["playlist"]["thumbnail_src"]
203 .get::<String>()
204 .expect("Error while unpacking thumbnail url")
205 .clone(),
206 video_count: item["playlist"]["video_count"]
207 .get::<String>()
208 .expect("Error while unpacking video count")
209 .clone(),
210 };
211 let uploader = PlaylistUploaderData {
212 username: item["uploader"]["username"]
213 .get::<String>()
214 .expect("Error while unpacking channel url")
215 .clone(),
216 url: item["uploader"]["url"]
217 .get::<String>()
218 .expect("Error while unpacking channel url")
219 .clone(),
220 };
221 data.push(Item::Playlist(playlist, uploader));
222 } else {
223 data.push(Item::Unknown);
224 }
225 }
226 data
227}