1mod conversions;
2mod models;
3
4use std::{cmp::min, error::Error};
5use crate::models::{country_model::Country, arguments::Arguments};
6use clap::Parser;
7use scraper::{ElementRef, Html, Selector};
8
9use crate::conversions::conversion;
10
11const URL: &str = "https://www.worldometers.info/coronavirus/";
12
13pub async fn run() -> Result<(), Box<dyn Error>> {
14 let args = get_parsed_arguments();
15 let address_string = String::from("https://www.worldometers.info/coronavirus/");
16 let resp = get_raw_text().await?;
17
18 let fragment = Html::parse_fragment(&resp);
19 let main_table = Selector::parse("table#main_table_countries_today tbody").unwrap();
20 let table_fragment = fragment.select(&main_table).next().unwrap();
21 let world_row_selector = Selector::parse("tr.total_row_world:not([data-continent])")
22 .expect("Could not find the world row");
23 let country_row_selector =
24 Selector::parse(r#"tr[style=""]"#).expect("Could not find the country rows");
25
26 let world_rows: Vec<ElementRef> = table_fragment.select(&world_row_selector).collect();
27 let rows: Vec<ElementRef> = table_fragment.select(&country_row_selector).collect();
28
29 let mut items = parse_for_countries(rows);
30 items.sort_by(|a, b| b.total_cases.cmp(&a.total_cases));
31
32 let row_count: usize = min(args.count.into(), items.len());
33 if !args.world_stats {
34 let mut temp_items = parse_for_countries(world_rows);
35 temp_items.append(&mut items);
36 items = temp_items;
37 }
38
39 println!(
40 "\n\nSource: {} as of {}",
41 address_string,
42 chrono::Local::now().to_rfc2822()
43 );
44 let table = conversion::convert_row_items_for_table(&items[0..row_count], args.show_full);
45 println!("{}", table.display().unwrap());
46 Ok(())
47}
48
49async fn get_raw_text() -> Result<String, reqwest::Error> {
50 let address_string = String::from(URL);
51 reqwest::get(&address_string).await?.text().await
52}
53fn get_parsed_arguments() -> Arguments {
54 Arguments::parse()
55}
56
57fn parse_for_countries(raw_data: Vec<ElementRef>) -> Vec<Country> {
58 let mut parsed: Vec<Country> = Vec::new();
59 for row in raw_data {
60 let td_sel = Selector::parse("td").expect("error parsing row");
61 let tds: Vec<ElementRef> = row.select(&td_sel).collect();
62 parsed.push(Country::build(&tds))
63 }
64 parsed
65}