diff options
Diffstat (limited to 'src/parser.rs')
| -rw-r--r-- | src/parser.rs | 220 |
1 files changed, 94 insertions, 126 deletions
diff --git a/src/parser.rs b/src/parser.rs index 5a670b1..f4fd2da 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,146 +1,114 @@ -use reqwest::{Error, Client, get}; -use chrono::{DateTime, Utc, prelude::*}; -use serde::{Serialize, Deserialize}; - -use crate::configmanager; - -//API answer struct`s -#[derive(Debug, Serialize, Deserialize)] -pub struct WeatherData { - pub lat: f64, - pub lon: f64, - pub timezone: String, - pub timezone_offset: i32, - pub current: Current, - pub minutely: Vec<Minutely>, - pub hourly: Vec<Hourly>, - pub daily: Vec<Daily>, - pub alerts: Vec<Alert>, -} +use reqwest::Client; +use std::fs::{self, File}; +use std::io::Read; +use toml; +use serde::Deserialize; +use serde_json; -#[derive(Debug, Serialize, Deserialize)] -pub struct Current { - pub dt: u64, - pub sunrise: u64, - pub sunset: u64, - pub temp: f32, - pub feels_like: f32, - pub pressure: u32, - pub humidity: u32, - pub dew_point: f32, - pub uvi: f32, - pub clouds: u32, - pub visibility: u32, - pub wind_speed: f32, - pub wind_deg: u32, - pub wind_gust: f32, - pub weather: Vec<Weather>, -} +// use crate::configmanager::Config; +use crate::shared::*; -#[derive(Debug, Serialize, Deserialize)] -pub struct Weather { - pub id: u32, - pub main: String, - pub description: String, - pub icon: String, -} +pub type BoxedError = Box<dyn std::error::Error + Send + Sync>; -#[derive(Debug, Serialize, Deserialize)] -pub struct Minutely { - pub dt: u64, - pub precipitation: f32, +fn get_config_path() -> Result<String, Box<dyn std::error::Error>> { + let home = std::env::var("HOME")?; + Ok(format!("{}/.config/WeatherFetch/Config.toml", home)) } -#[derive(Debug, Serialize, Deserialize)] -pub struct Hourly { - pub dt: u64, - pub temp: f32, - pub feels_like: f32, - pub pressure: u32, - pub humidity: u32, - pub dew_point: f32, - pub uvi: f32, - pub clouds: u32, - pub visibility: u32, - pub wind_speed: f32, - pub wind_deg: u32, - pub wind_gust: f32, - pub weather: Vec<Weather>, - pub pop: f32, -} +/* +const CONF: Lazy<Result<Config, Box<dyn std::error::Error + Send + Sync>>> = Lazy::new(|| { + Config::load().map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>) +}); +*/ -#[derive(Debug, Serialize, Deserialize)] -pub struct Daily { - pub dt: u64, - pub sunrise: u64, - pub sunset: u64, - pub moonrise: u64, - pub moonset: u64, - pub moon_phase: f32, - pub summary: String, - pub temp: Temp, - pub feels_like: FeelsLike, - pub pressure: u32, - pub humidity: u32, - pub dew_point: f32, - pub wind_speed: f32, - pub wind_deg: u32, - pub wind_gust: f32, - pub weather: Vec<Weather>, - pub clouds: u32, - pub pop: f32, - pub rain: Option<f32>, - pub uvi: f32, -} +pub fn get_location(coords_args: bool) -> Result<(), BoxedError> { + let config = get_config().unwrap(); -#[derive(Debug, Serialize, Deserialize)] -pub struct Temp { - pub day: f32, - pub min: f32, - pub max: f32, - pub night: f32, - pub eve: f32, - pub morn: f32, + if (config.lat == 0.0 || config.lon == 0.0) && !coords_args { + + println!("No coordinates in configuration file or conf not founded."); + println!("HINT: Try create ~/.config/WeatherFetch/Config.toml"); + println!("HINT: And add `lat(<float>)`, `lon(<float>)`."); + println!("HINT: To get more info check https://open-meteo.com/en/docs"); + + Err("Invalid coordinates in config".into()) + } else { + Ok(()) + } } -#[derive(Debug, Serialize, Deserialize)] -pub struct FeelsLike { - pub day: f32, - pub night: f32, - pub eve: f32, - pub morn: f32, +pub async fn parse_weather() -> Result<WeatherData, Box<dyn std::error::Error>> { + let config = get_config()?; + let client = Client::new(); + let response = client.get("https://api.open-meteo.com/v1/forecast") + .query(&[ + ("latitude", config.lat.to_string()), + ("longitude", config.lon.to_string()), + ("current", "temperature_2m,wind_speed_10m".to_string()), + ("hourly", "temperature_2m,relative_humidity_2m,wind_speed_10m".to_string()), + ]) + .send() + .await?; + + let response_text = response.text().await?; + + let weather_data: WeatherData = serde_json::from_str(&response_text)?; + + let home = std::env::var("HOME")?; + let cache_dir = format!("{}/.cache/WeatherFetch", home); + fs::create_dir_all(&cache_dir)?; + + let cache_path = format!("{}/weather.json", cache_dir); + let json_data = serde_json::to_string_pretty(&weather_data)?; + fs::write(&cache_path, json_data)?; + + Ok(weather_data) } -#[derive(Debug, Serialize, Deserialize)] -pub struct Alert { - pub sender_name: String, - pub event: String, - pub start: u64, - pub end: u64, - pub description: String, - pub tags: Vec<String>, + +#[derive(Debug, Deserialize)] +pub struct Config { + lat: f64, + lon: f64, + exclude: String, + appid: String, + units: String, + lang: String, } +pub fn get_config() -> Result<Config, Box<dyn std::error::Error>> { + let config_path = get_config_path()?; + + if File::open(&config_path).is_err() { + generate_config()?; + } + + let mut file = File::open(&config_path)?; + let mut content = String::new(); + file.read_to_string(&mut content)?; + let config: Config = toml::from_str(&content)?; + Ok(config) +} +pub fn generate_cachedir() -> Result<(), Box<dyn std::error::Error>> { + let home = std::env::var("HOME")?; + let cache_path = format!("{}/.cache/WeatherFetch/", home); + + let _ = fs::create_dir(cache_path); -pub fn get_location(coords_args: bool) -> Result<(), String>{ - //Get the lat and lon for API call - let conf: Option<configmanager::load()>; - if conf.lat.is_empty() || conf.lon.is_empty() && !coords_args{ - println!("No coordinates in configuration file or conf not founded."); - println!("HINT: Try create ~/.config/WeatherFetch/Config.toml"); - println!("HINT: And add `lat(<int>)`, `lon(<int>)`."); - println!("HINT: To get more info check https://openweathermap.org/api/one-call-3"); + Ok(()) +} - Err("No coordinates in config or args.".into()) - } else { - Ok(()) +pub fn generate_config() -> Result<(), Box<dyn std::error::Error>> { + let config_path = get_config_path()?; + let config = "lat = 55.75\nlon = 37.62\nexclude = \"\"\nappid = \"\"\nunits = \"metric\"\nlang = \"ru\""; + let path = std::path::Path::new(&config_path); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; } -} - - -pub async fn parse_weather(_config: &Config) -> Result<(), reqwest::Error> { + fs::write(path, config)?; + println!("Config file generated at: {}", config_path); Ok(()) -} +}
\ No newline at end of file |
