use indexmap::IndexMap; use log::{error, info, LevelFilter}; use serde_derive::Deserialize; use simple_logger::SimpleLogger; #[cfg(target_os = "windows")] use std::io; use std::io::Error; #[cfg(target_os = "windows")] use std::io::ErrorKind; use std::path::PathBuf; use std::{fs, thread, time}; use time::Duration; #[cfg(target_os = "windows")] use winreg::RegKey; mod cgg_data_source; mod data_source; mod kb_data_source; mod pb_data_source; use cgg_data_source::CGGDataSource; use data_source::DataSource; use kb_data_source::KBDataSource; use pb_data_source::PBDataSource; #[derive(Deserialize)] struct Realm { v: String, } #[derive(Deserialize)] struct Champion { data: IndexMap, } #[derive(Deserialize)] pub struct ChampInfo { id: String, name: String, key: String, } const USER_AGENT_KEY: &str = "User-Agent"; const USER_AGENT_VALUE: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0"; const LOL_CHAMPS_DIR: &str = ".\\champs"; fn main() { SimpleLogger::new() .with_level(LevelFilter::Info) .with_module_level("ureq", LevelFilter::Error) .init() .unwrap(); info!("CGG Item Sets"); let lol_champs_dir = match lol_champ_dir() { Ok(x) => x, Err(_e) => PathBuf::from(LOL_CHAMPS_DIR), }; info!("LoL Champs Folder: {}", lol_champs_dir.to_str().unwrap()); let client = ureq::AgentBuilder::new() .timeout(Duration::from_secs(10)) .build(); let realm: Realm = client .get("https://ddragon.leagueoflegends.com/realms/euw.json") .set(USER_AGENT_KEY, USER_AGENT_VALUE) .call() .unwrap() .into_json() .unwrap(); info!("LoL version: {}", realm.v); let champion: Champion = client .get(&format!( "https://ddragon.leagueoflegends.com/cdn/{}/data/en_US/champion.json", realm.v )) .set(USER_AGENT_KEY, USER_AGENT_VALUE) .call() .unwrap() .into_json() .unwrap(); info!("LoL numbers of champs: {}", champion.data.len()); let data_sources: [Box; 3] = [ Box::new(PBDataSource), Box::new(CGGDataSource), Box::new(KBDataSource::new(&client)), ]; for data_source in data_sources.iter() { let (champs, patch) = data_source.get_champs_with_positions_and_patch(&client); info!("{} version: {}", data_source.get_alias(), patch); info!( "{} numbers of champs: {}", data_source.get_alias(), champs.len() ); for (id, positions) in &champs { let mut champ_id: String = id.to_owned(); if !champion.data.contains_key(&champ_id) { champ_id = get_champ_from_key(&champion, &champ_id); } if champion.data.contains_key(&champ_id) { let path = lol_champs_dir.join(&champ_id).join("Recommended"); fs::create_dir_all(&path).unwrap(); if positions.is_empty() { error!("{} missing positions", &champ_id); } for pos in positions { data_source.write_item_set( &champion.data.get(&champ_id).unwrap(), &pos, &patch, &path, &client, ); thread::sleep(Duration::from_millis(data_source.get_timeout())); } } else { error!("{} not found in LoL champs", &champ_id); } } } } fn get_champ_from_key(champs: &Champion, key: &str) -> String { for champ in champs.data.values() { if key == champ.key { return champ.id.to_owned(); } } String::new() } #[cfg(target_os = "windows")] fn lol_champ_dir() -> Result { let hklm = RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE); let node = hklm.open_subkey(r"SOFTWARE\WOW6432Node\Riot Games\RADS"); if node.is_ok() { let val: String = node?.get_value("LocalRootFolder")?; return Ok(PathBuf::from(val).parent().unwrap().to_path_buf()); } else { let node = hklm.open_subkey(r"SOFTWARE\WOW6432Node\Riot Games, Inc\League of Legends"); if node.is_ok() { let val: String = node?.get_value("Location")?; return Ok(PathBuf::from(val)); } } let node = hklm.open_subkey(r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"); let mut sub_node: io::Result = Err(Error::from(ErrorKind::NotFound)); if let Ok(n) = node { let key = n .enum_keys() .map(|x| x.unwrap()) .find(|x| x.starts_with("League of Legends")); if let Some(k) = key { sub_node = n.open_subkey(k); } } if sub_node.is_err() { let hkcu = RegKey::predef(winreg::enums::HKEY_CURRENT_USER); let node = hkcu.open_subkey(r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"); if let Ok(n) = node { let key = n .enum_keys() .map(|x| x.unwrap()) .find(|x| x == "Riot Game league_of_legends.live"); if let Some(k) = key { sub_node = n.open_subkey(k); } } } if sub_node.is_ok() { let val: String = sub_node?.get_value("InstallLocation")?; return Ok(PathBuf::from(val).join("Config").join("Champions")); } Err(Error::from(ErrorKind::NotFound)) } #[cfg(not(target_os = "windows"))] fn lol_champ_dir() -> Result { Ok(PathBuf::from(LOL_CHAMPS_DIR)) }