swas/
lib.rs

1//! A library that tells you when swas will upload new video
2//! (Also lets you search his youtube videos and get metadata about his videos)
3
4use std::collections::HashMap;
5use tinyjson::JsonValue;
6
7
8/// Data related to youtube channel
9
10#[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/// Data related to a video
24
25#[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/// Data related to youtube playlist
38
39#[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/// Data related to a video uploader
49
50#[allow(dead_code)]
51#[derive(Debug)]
52pub struct VideoUploaderData {
53    pub username: String,
54    pub url: String,
55    pub verified: bool,
56}
57/// Data related to a playlist uploader
58
59#[allow(dead_code)]
60#[derive(Debug)]
61pub struct PlaylistUploaderData {
62    pub username: String,
63    pub url: String,
64}
65/// Packs all possible types of parsed youtube items
66
67#[derive(Debug)]
68pub enum Item {
69    /// Encaptulates channels
70    Channel(ChannelData),
71    /// Encaptulates videos
72    Video(VideoData, VideoUploaderData),
73    /// Encaptulates playlists
74    Playlist(PlaylistData, PlaylistUploaderData),
75    /// Any other types(idk) go here
76    Unknown,
77}
78/// Returns the scraped youtube result based on the query
79/// # Example
80/// ```
81/// let resp = swas::raw_search_with_title("Code with swastik").expect("Error fetching data");
82/// println!("{:?}", resp);
83/// ```
84pub 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}