diff --git a/src/data_source.rs b/src/data_source.rs index 7084132..a62dc38 100644 --- a/src/data_source.rs +++ b/src/data_source.rs @@ -70,7 +70,7 @@ pub trait DataSource { positions: &[String], path: &Path, client: &ureq::Agent, - ) { + ) -> Result<(), Box> { info!( "{}: Retrieving data for {} at {}", self.get_alias(), @@ -126,6 +126,10 @@ pub trait DataSource { champ.name, build.0 ); + + let json_string = serde_json::to_string_pretty(&item_set) + .map_err(|e| format!("Failed to serialize item set: {}", e))?; + fs::write( path.join(format!( "{}_{}_{}.json", @@ -133,9 +137,10 @@ pub trait DataSource { champ.id, build.0 )), - serde_json::to_string_pretty(&item_set).unwrap(), + json_string, ) - .unwrap(); + .map_err(|e| format!("Failed to write item set file: {}", e))?; } + Ok(()) } } diff --git a/src/main.rs b/src/main.rs index 3bc6528..b33c033 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,7 +74,7 @@ fn main() -> Result<(), Box> { Ok(x) => x, Err(_e) => PathBuf::from(DEFAULT_LOL_CHAMPS_DIR), }; - info!("LoL Champs Folder: {}", lol_champs_dir.to_str().unwrap()); + info!("LoL Champs Folder: {}", lol_champs_dir.display()); let client: Agent = Agent::config_builder() .user_agent(USER_AGENT_VALUE) @@ -175,8 +175,21 @@ fn get_and_write_item_set( error!("{}: {} empty positions", data_source.get_alias(), &champ_id); } else { let path = lol_champs_dir.join(&champ_id).join("Recommended"); - fs::create_dir_all(&path).unwrap(); - data_source.write_item_set(champ, positions, &path, client); + match fs::create_dir_all(&path) { + Ok(_) => match data_source.write_item_set(champ, positions, &path, client) { + Ok(_) => (), + Err(e) => error!( + "{}: Failed to write item set for {} at {}: {}", + data_source.get_alias(), + champ.name, + positions.join(", "), + e + ), + }, + Err(e) => { + error!("Failed to create directory for {}: {}", champ_id, e); + } + } } } else { error!("{} not found in LoL champs", &champ_id); @@ -193,8 +206,10 @@ fn lol_champ_dir() -> Result { REG_KEY_LOL_RADS ); let val: String = node.get_value("LocalRootFolder")?; - // TODO: remplacer ce .unwrap() - PathBuf::from(val).parent().unwrap().to_path_buf() + match PathBuf::from(val).parent() { + Some(parent) => parent.to_path_buf(), + None => return Err(Error::from(ErrorKind::NotFound)), + } } else if let Ok(node) = hklm.open_subkey(REG_KEY_LOL_INC) { debug!( "Use registry key {} for relative champ directory", @@ -238,7 +253,7 @@ fn find_subnode_from_path(reg: RegKey, path: &str, key: &str) -> io::Result Option { for champ in champs.data.values() { if name == champ.name || name == champ.id { - return Some(champ.key.parse::().unwrap()); + return champ.key.parse::().ok(); } } None } fn find_next_number(rest: &str) -> f32 { - let re = Regex::new(r"([0-9]+\.?[0-9]+)").unwrap(); - if let Some(cap) = re.captures(rest) { - if let Some(matched) = cap.get(1) { - return matched.as_str().parse::().unwrap_or(0.0); + let re = Regex::new(r"([0-9]+\.?[0-9]+)"); + if let Ok(re) = re { + if let Some(cap) = re.captures(rest) { + if let Some(matched) = cap.get(1) { + return matched.as_str().parse::().unwrap_or(0.0); + } } } 0.0 @@ -51,24 +54,28 @@ impl DataSource for MSDataSource { ) -> IndexMap> { let mut champs = IndexMap::new(); - let champions: Vec = client + let champions: Vec = match client .get("https://www.metasrc.com/lol/search/lol") .call() - .unwrap() - .body_mut() - .read_json() - .unwrap(); + .and_then(|mut resp| resp.body_mut().read_json()) + { + Ok(champs) => champs, + Err(_) => return champs, + }; for champ in champions { - let id = get_champ_from_name(champion, champ.name).unwrap(); - let allowed_roles = ["TOP", "ADC", "SUPPORT", "JUNGLE", "MID"]; - let roles = champ - .search_terms - .split('|') - .map(|s| s.to_uppercase()) - .filter(|role| allowed_roles.contains(&role.as_str())) - .collect::>(); - champs.insert(id, roles); + if let Some(id) = get_champ_from_name(champion, champ.name.to_owned()) { + let allowed_roles = ["TOP", "ADC", "SUPPORT", "JUNGLE", "MID"]; + let roles = champ + .search_terms + .split('|') + .map(|s| s.to_uppercase()) + .filter(|role| allowed_roles.contains(&role.as_str())) + .collect::>(); + champs.insert(id, roles); + } else { + error!("Could not find champ {} in champion data", champ.name); + } } champs @@ -93,26 +100,47 @@ impl DataSource for MSDataSource { ) .call(); if let Ok(mut p) = rep { - let page = p.body_mut().read_to_string().unwrap(); - let mut pos = page.find("Patch ").unwrap(); - let patch = find_next_number(&page[pos..]).to_string(); + let page = match p.body_mut().read_to_string() { + Ok(s) => s, + Err(_) => return builds, + }; - pos = page.find("Win").unwrap(); - let win_rate: f32 = find_next_number(&page[pos..]); + let mut pos = page.find("Patch "); + let patch = if let Some(p) = pos { + find_next_number(&page[p..]).to_string() + } else { + String::new() + }; - pos = page.find("KDA:").unwrap(); - let kda: f32 = find_next_number(&page[pos..]); + pos = page.find("Win"); + let win_rate: f32 = if let Some(p) = pos { + find_next_number(&page[p..]) + } else { + 0.0 + }; - pos = page.find("Games:").unwrap(); - let games: u32 = find_next_number(&page[pos..]) as u32; + pos = page.find("KDA:"); + let kda: f32 = if let Some(p) = pos { + find_next_number(&page[p..]) + } else { + 0.0 + }; + + pos = page.find("Games:"); + let games: u32 = if let Some(p) = pos { + find_next_number(&page[p..]) as u32 + } else { + 0 + }; let mut items = vec![]; let mut pos: Option = page.find("/item/"); while let Some(mut p) = pos { p += 6; - let i = &page[p..p + page[p..].find('.').unwrap()]; - - items.push(i); + if let Some(dot_pos) = page[p..].find('.') { + let i = &page[p..p + dot_pos]; + items.push(i); + } let next = page[p..].find("/item/"); if let Some(n) = next {