Adding cache for IpLocation
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@ -1,5 +1,9 @@
|
||||
pub fn extract_coords_and_city(ip: &str) -> Result<serde_json::Value, ureq::Error> {
|
||||
use crate::ip_location::IpLocation;
|
||||
|
||||
pub fn extract_coords_and_city(ip: &str) -> Result<IpLocation, ureq::Error> {
|
||||
let url = format!("http://ip-api.com/json/{}?fields=16592", ip);
|
||||
let body: serde_json::Value = ureq::get(&url).call()?.into_json()?;
|
||||
Ok(body)
|
||||
|
||||
let current_weather: IpLocation = serde_json::from_value(body).unwrap();
|
||||
Ok(current_weather)
|
||||
}
|
||||
|
8
src/ip_location.rs
Normal file
8
src/ip_location.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct IpLocation {
|
||||
pub lat: f64,
|
||||
pub lon: f64,
|
||||
pub city: String,
|
||||
}
|
68
src/ip_location_cache.rs
Normal file
68
src/ip_location_cache.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use std::{
|
||||
fs::{create_dir_all, File},
|
||||
io::{Read, Write},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use crate::ip_location::IpLocation;
|
||||
use directories::ProjectDirs;
|
||||
pub fn save_to_cache(ip: &str, data: &IpLocation) {
|
||||
let cache_dir = get_cache_dir();
|
||||
if cache_dir.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut cache_dir = cache_dir.unwrap();
|
||||
cache_dir.push(format!("{}.{}", ip, "json"));
|
||||
|
||||
let json = serde_json::to_string(data).expect("Error al serializar a JSON");
|
||||
let mut file = File::create(&cache_dir).expect("Error al crear el archivo");
|
||||
file.write_all(json.as_bytes())
|
||||
.expect("Error al escribir en el archivo");
|
||||
}
|
||||
|
||||
pub fn get_from_cache(ip: &str) -> Option<IpLocation> {
|
||||
let cache_dir = get_cache_dir();
|
||||
if cache_dir.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut cache_dir = cache_dir.unwrap();
|
||||
cache_dir.push(format!("{}.{}", ip, "json"));
|
||||
|
||||
if !is_in_cache(&cache_dir) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut file = File::open(&cache_dir).expect("Error al abrir el archivo");
|
||||
let mut content = String::new();
|
||||
file.read_to_string(&mut content)
|
||||
.expect("Error al leer el archivo");
|
||||
|
||||
let ip_location: IpLocation =
|
||||
serde_json::from_str(&content).expect("Error al deserializar JSON");
|
||||
Some(ip_location)
|
||||
}
|
||||
|
||||
fn is_in_cache(path: &PathBuf) -> bool {
|
||||
path.is_file()
|
||||
}
|
||||
|
||||
fn get_cache_dir() -> Option<PathBuf> {
|
||||
let dir = ProjectDirs::from("com", "midefos", "open-meteo-cli");
|
||||
if dir.is_some() {
|
||||
let project_dir = dir.unwrap();
|
||||
|
||||
let cache_dir = project_dir.cache_dir();
|
||||
if !cache_dir.exists() {
|
||||
let res = create_dir_all(cache_dir);
|
||||
if res.is_err() {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Some(cache_dir.to_owned())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
31
src/main.rs
31
src/main.rs
@ -4,25 +4,26 @@ mod current_weather;
|
||||
mod current_weather_extractor;
|
||||
mod current_weather_output;
|
||||
mod current_weather_output_model;
|
||||
|
||||
mod current_weather_print_params;
|
||||
mod data_format;
|
||||
mod ifconfig;
|
||||
mod ip_api;
|
||||
mod ip_location;
|
||||
mod ip_location_cache;
|
||||
mod open_meteo;
|
||||
mod speed_unit;
|
||||
mod temp_unit;
|
||||
|
||||
use billboard::{Alignment, Billboard};
|
||||
use current_weather_print_params::CurrentWeatherPrintParams;
|
||||
use data_format::DataFormat;
|
||||
use ip_location_cache::{get_from_cache, save_to_cache};
|
||||
use std::process::exit;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use cli::Arguments;
|
||||
use coords::Coordinates;
|
||||
|
||||
use current_weather_extractor::CurrentWeatherExtractor;
|
||||
use current_weather_print_params::CurrentWeatherPrintParams;
|
||||
use ifconfig::extract_public_ip;
|
||||
use ip_api::extract_coords_and_city;
|
||||
use open_meteo::request_current_weather;
|
||||
@ -82,16 +83,24 @@ fn main() {
|
||||
exit(1);
|
||||
});
|
||||
|
||||
let coords_result = extract_coords_and_city(&ip);
|
||||
let coords = coords_result.unwrap_or_else(|_| {
|
||||
eprintln!("[ERROR] Could not extract IP coordinates from ip_api");
|
||||
exit(1);
|
||||
});
|
||||
let ip_location;
|
||||
let cache_ip_location = get_from_cache(&ip);
|
||||
|
||||
let latitude = coords["lat"].as_f64().unwrap();
|
||||
let longitude = coords["lon"].as_f64().unwrap();
|
||||
if cache_ip_location.is_some() {
|
||||
ip_location = cache_ip_location.unwrap();
|
||||
} else {
|
||||
let ip_location_res = extract_coords_and_city(&ip);
|
||||
ip_location = ip_location_res.unwrap_or_else(|_| {
|
||||
eprintln!("[ERROR] Could not extract IP location from ip_api");
|
||||
exit(1);
|
||||
});
|
||||
save_to_cache(&ip, &ip_location);
|
||||
}
|
||||
|
||||
let latitude = ip_location.lat;
|
||||
let longitude = ip_location.lon;
|
||||
coordinates = Coordinates::new(latitude, longitude);
|
||||
city = Some(coords["city"].as_str().unwrap().to_string());
|
||||
city = Some(ip_location.city);
|
||||
}
|
||||
|
||||
let result = request_current_weather(&coordinates, &temperature_unit, &speed_unit);
|
||||
|
Reference in New Issue
Block a user