abgespaced

An API that combines The DB Bahnhof API and the Space API
git clone git://archive.git.mtrnord.blog/MTRNord/abgespaced.git
Log | Files | Refs

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 }