You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
3.3 KiB
74 lines
3.3 KiB
use clap::Parser;
|
|
use derive_more::From;
|
|
use scraper::{Html, Selector};
|
|
use colored::Colorize;
|
|
|
|
#[derive(Default, Parser)]
|
|
#[clap(author, version, about)]
|
|
struct Arguments {
|
|
#[clap(help = "Plume Labs location ID. For example, https://air.plumelabs.com/air-quality-in-XXX")]
|
|
location: String,
|
|
#[clap(short, long, help = "Display raw Air Quality Index")]
|
|
raw: bool,
|
|
#[clap(short, long, help = "Display AccuWeather Air Quality Index description")]
|
|
description: bool,
|
|
}
|
|
|
|
#[derive(From, Debug)]
|
|
enum Error {
|
|
ReqwestError(reqwest::Error),
|
|
HttpError,
|
|
InvalidResponse,
|
|
}
|
|
|
|
fn main() -> Result<(), Error> {
|
|
let arguments = Arguments::parse();
|
|
let response = reqwest::blocking::get(format!("https://air.plumelabs.com/air-quality-in-{}", arguments.location))?;
|
|
if !response.status().is_success() {
|
|
return Err(Error::HttpError);
|
|
}
|
|
let content = response.text_with_charset("utf-8")?;
|
|
let document = Html::parse_document(&content);
|
|
let selector = Selector::parse("span[data-role=\"current-pi\"]").unwrap();
|
|
let aqi = match match document.select(&selector).next() {
|
|
Some(element) => element,
|
|
None => return Err(Error::InvalidResponse),
|
|
}.inner_html().trim().parse::<f32>() {
|
|
Ok(aqi) => aqi,
|
|
Err(_) => return Err(Error::InvalidResponse),
|
|
} as u32;
|
|
if arguments.raw {
|
|
println!("{}", aqi);
|
|
return Ok(());
|
|
}
|
|
println!("{} {}",
|
|
match aqi {
|
|
250.. => "Dangerous".purple(),
|
|
150.. => "Very Unhealthy".purple(),
|
|
100.. => "Unhealthy".magenta(),
|
|
50.. => "Poor".red(),
|
|
20.. => "Fair".yellow(),
|
|
0.. => "Excellent".green(),
|
|
}.bold(),
|
|
match aqi {
|
|
// 250.. => (no appropriate terminal color) // Dangerous 250+
|
|
150.. => aqi.to_string().purple(), // Very Unhealthy 150-249
|
|
100.. => aqi.to_string().magenta(), // Unhealthy 100-149
|
|
50.. => aqi.to_string().red(), // Poor 50-99
|
|
20.. => aqi.to_string().yellow(), // Fair 20-49
|
|
0.. => aqi.to_string().green(), // Excellent 0-19
|
|
}.bold()
|
|
);
|
|
if arguments.description {
|
|
println!("{}", match aqi {
|
|
250.. => "Any exposure to the air, even for a few minutes, can lead to serious health effects on everybody. Avoid outdoor activities.",
|
|
150.. => "Health effects will be immediately felt by sensitive groups and should avoid outdoor activity. Healthy individuals are likely to experience difficulty breathing and throat irritation; consider staying indoors and rescheduling outdoor activities.",
|
|
100.. => "Health effects can be immediately felt by sensitive groups. Healthy individuals may experience difficulty breathing and throat irritation with prolonged exposure. Limit outdoor activity.",
|
|
50.. => "The air has reached a high level of pollution and is unhealthy for sensitive groups. Reduce time spent outside if you are feeling symptoms such as difficulty breathing or throat irritation.",
|
|
20.. => "The air quality is generally acceptable for most individuals. However, sensitive groups may experience minor to moderate symptoms from long-term exposure.",
|
|
0.. => "The air quality is ideal for most individuals; enjoy your normal outdoor activities.",
|
|
});
|
|
}
|
|
return Ok(());
|
|
}
|