spaceapi.rs (7046B)
1 use reqwest::StatusCode; 2 use serde::*; 3 use serde_json::Value; 4 use std::collections::HashMap; 5 use std::fs; 6 use std::fs::File; 7 use std::path::Path; 8 use std::time::{Duration, SystemTime}; 9 use std::io::BufReader; 10 11 fn get_spaces_web() -> Result<HashMap<String, HashMap<String, f64>>, failure::Error> { 12 let client = reqwest::Client::builder() 13 .gzip(true) 14 .timeout(Duration::from_secs(10)) 15 .build()?; 16 17 let mut res = client.get("https://directory.spaceapi.io/").send()?; 18 19 let json: Value = res.json()?; 20 21 fs::create_dir_all("./tmp/")?; 22 let serialized = serde_json::to_string(&json).unwrap(); 23 fs::write("./tmp/spaces.json", serialized).expect("Unable to write file"); 24 25 let mut spaces = HashMap::new(); 26 for (key, value) in json.as_object().unwrap().iter() { 27 let space: Result<HashMap<String, f64>, failure::Error> = get_space( 28 key.as_str().to_string(), 29 value.as_str().unwrap().to_string(), 30 ); 31 if space.is_ok() { 32 spaces.insert(key.to_string(), space.unwrap()); 33 } 34 } 35 36 //println!("{:?}", json); 37 Ok(spaces) 38 } 39 40 pub fn get_spaces() -> Result<HashMap<String, HashMap<String, f64>>, failure::Error> { 41 if Path::new("./tmp/spaces.json").exists() { 42 let cache_data = fs::metadata("./tmp/spaces.json")?; 43 44 if let Ok(time) = cache_data.modified() { 45 let now = SystemTime::now(); 46 if now.duration_since(time).unwrap() >= Duration::from_secs(86400) { 47 return get_spaces_web(); 48 } else { 49 let cache_file = File::open(Path::new("./tmp/spaces.json"))?; 50 let reader = BufReader::new(cache_file); 51 let json: Value = serde_json::from_reader(reader)?; 52 53 let mut spaces = HashMap::new(); 54 for (key, value) in json.as_object().unwrap().iter() { 55 info!("{}: {}", key, value); 56 info!("GetSpace"); 57 let space: Result<HashMap<String, f64>, failure::Error> = get_space( 58 key.as_str().to_string(), 59 value.as_str().unwrap().to_string(), 60 ); 61 if space.is_ok() { 62 spaces.insert(key.to_string(), space.unwrap()); 63 } 64 } 65 66 //println!("{:?}", json); 67 return Ok(spaces); 68 } 69 } else { 70 return get_spaces_web(); 71 } 72 } else { 73 return get_spaces_web(); 74 } 75 } 76 77 #[derive(Serialize, Deserialize)] 78 pub struct Location { 79 address: String, 80 lon: f64, 81 lat: f64, 82 } 83 84 #[derive(Serialize, Deserialize)] 85 pub struct Space { 86 api: String, 87 space: String, 88 logo: String, 89 url: String, 90 location: Location, 91 contact: Value, 92 issue_report_channels: Vec<String>, 93 state: Value, 94 open: Option<bool>, 95 } 96 97 fn get_space_web(name: String, url: String) -> Result<HashMap<String, f64>, failure::Error> { 98 let client = reqwest::Client::builder() 99 .gzip(true) 100 .timeout(Duration::from_secs(10)) 101 .build()?; 102 103 let mut res = client.get(url.as_str()).send()?; 104 105 if res.status() == StatusCode::OK { 106 let json: Space = res.json()?; 107 fs::create_dir_all("./tmp/spaces/")?; 108 let serialized = serde_json::to_string(&json).unwrap(); 109 let file_name_path = format!("./tmp/spaces/space_{}.json", name.replace("/", "_")); 110 fs::write(&file_name_path, serialized) 111 .expect(format!("Unable to write file: {:?}", file_name_path).as_str()); 112 113 let mut map = HashMap::new(); 114 115 map.insert("lat".to_string(), json.location.lat); 116 map.insert("lon".to_string(), json.location.lon); 117 //println!("{:?}", json); 118 return Ok(map); 119 } 120 Err(failure::err_msg("SPACE API DOWN")) 121 } 122 123 pub fn get_space(name: String, url: String) -> Result<HashMap<String, f64>, failure::Error> { 124 let file_name_path = format!("./tmp/spaces/space_{}.json", name.replace("/", "_")); 125 let space_file = Path::new(&file_name_path); 126 if space_file.exists() { 127 info!("1"); 128 let cache_data = fs::metadata(&space_file)?; 129 130 if let Ok(time) = cache_data.modified() { 131 let now = SystemTime::now(); 132 if now.duration_since(time).unwrap() >= Duration::from_secs(86400) { 133 return get_space_web(name, url); 134 } else { 135 info!("2"); 136 let cache_file = File::open(&space_file)?; 137 let reader = BufReader::new(cache_file); 138 let json: Space = serde_json::from_reader(reader)?; 139 140 let mut map = HashMap::new(); 141 142 map.insert("lat".to_string(), json.location.lat); 143 map.insert("lon".to_string(), json.location.lon); 144 //println!("{:?}", json); 145 return Ok(map); 146 } 147 } else { 148 Err(failure::err_msg("modified Date Missing")) 149 } 150 } else { 151 return get_space_web(name, url); 152 } 153 } 154 155 pub fn find_space(name: &str) -> Result<HashMap<String, f64>, failure::Error> { 156 if Path::new("./tmp/spaces").exists() { 157 let file_name_path = format!("./tmp/spaces/space_{}.json", name.replace("/", "_")); 158 let space_file = Path::new(&file_name_path); 159 if space_file.exists() { 160 let cache_file = File::open(&space_file)?; 161 let reader = BufReader::new(cache_file); 162 let json: Space = serde_json::from_reader(reader)?; 163 164 let mut map = HashMap::new(); 165 166 map.insert("lat".to_string(), json.location.lat); 167 map.insert("lon".to_string(), json.location.lon); 168 //println!("{:?}", json); 169 return Ok(map); 170 } else { 171 let all_spaces = get_spaces(); 172 match all_spaces { 173 Ok(x) => { 174 let space: Option<HashMap<String, f64>> = 175 x.into_iter() 176 .find_map(|x| if x.0 == name { Some(x.1) } else { None }); 177 if space.is_some() { 178 Ok(space.unwrap()) 179 } else { 180 Err(failure::err_msg("Space not found")) 181 } 182 } 183 Err(e) => { 184 error!("{:?}", e); 185 return Err(e); 186 } 187 } 188 } 189 } else { 190 let all_spaces = get_spaces(); 191 match all_spaces { 192 Ok(x) => { 193 let space: Option<HashMap<String, f64>> = 194 x.into_iter() 195 .find_map(|x| if x.0 == name { Some(x.1) } else { None }); 196 if space.is_some() { 197 Ok(space.unwrap()) 198 } else { 199 Err(failure::err_msg("Space not found")) 200 } 201 } 202 Err(e) => { 203 error!("{:?}", e); 204 return Err(e); 205 } 206 } 207 } 208 }