diff --git a/Cargo.lock b/Cargo.lock index 40d84fc..54c951f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,15 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "base64" version = "0.22.1" @@ -36,6 +45,7 @@ dependencies = [ "indexmap", "log", "rayon", + "regex", "serde", "serde_derive", "serde_json", @@ -384,6 +394,35 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "ring" version = "0.17.14" @@ -726,8 +765,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winreg" -version = "0.52.0" -source = "git+https://github.com/phoval/winreg-rs.git#654fc8f983c91346c729198a7b58f7b76fb7a8f5" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" dependencies = [ "cfg-if", "windows-sys 0.59.0", diff --git a/Cargo.toml b/Cargo.toml index 28587a7..4b82747 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ include = ["src/**/*"] indexmap = {version = "2.2", features = ["serde", "rayon"]} log = "0.4" rayon = "1.10" +regex = "1.11.1" serde = "1.0" serde_derive = "1.0" serde_json = {version = "1.0", features = ["preserve_order"]} @@ -17,7 +18,7 @@ simple_logger = {git = 'https://github.com/phoval/rust-simple_logger.git', defau ureq = {version = "2.9", features = ["json"]} [target.'cfg(windows)'.dependencies] -winreg = { git = 'https://github.com/phoval/winreg-rs.git' } +winreg = { version = "0.55" } [profile.release] codegen-units = 1 diff --git a/src/ms_data_source.rs b/src/ms_data_source.rs index b4cfe6b..9ef0e7e 100644 --- a/src/ms_data_source.rs +++ b/src/ms_data_source.rs @@ -1,4 +1,6 @@ use indexmap::IndexMap; +use regex::Regex; +use serde_derive::Deserialize; use serde_json::Value; use crate::data_source::{DataSource, Stat}; @@ -7,7 +9,31 @@ use crate::Champion; pub struct MSDataSource; -const CHAMP_PATTERN: &str = " href=https://www.metasrc.com/5v5/champion/"; +#[derive(Deserialize)] +struct MSChampion { + name: String, + #[serde(rename = "search-terms")] + search_terms: String, +} + +fn get_champ_from_name(champs: &Champion, name: String) -> Option { + for champ in champs.data.values() { + if name == champ.name || name == champ.id { + return Some(champ.key.parse::().unwrap()); + } + } + None +} + +fn find_next_number(rest: &str) -> f32 { + let re = Regex::new(r"(\d+\.?\d+)").unwrap(); + 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 +} impl DataSource for MSDataSource { fn get_alias(&self) -> &str { @@ -25,33 +51,23 @@ impl DataSource for MSDataSource { ) -> IndexMap> { let mut champs = IndexMap::new(); - let page = client - .get("https://www.metasrc.com/5v5") + let champions: Vec = client + .get("https://www.metasrc.com/lol/search/lol") .call() .unwrap() - .into_string() + .into_json() .unwrap(); - let mut pos: Option = page.find(CHAMP_PATTERN); - while let Some(mut p) = pos { - p += CHAMP_PATTERN.len(); - let role = - &page[p + page[p..].find('/').unwrap() + 1..p + page[p..].find('>').unwrap()]; - - let k = p + page[p..].find("data-search-terms-like=").unwrap() + 23; - let pipe = k + page[k..].find('|').unwrap() + 1; - let key = &page[pipe..pipe + page[pipe..].find(' ').unwrap()].replace('\"', ""); - - let id = champion.data.get(key).unwrap().key.parse::().unwrap(); - - champs.insert(id, vec![role.to_uppercase()]); - - let next = page[p..].find(CHAMP_PATTERN); - if let Some(n) = next { - pos = Some(p + n); - } else { - pos = None; - } + 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); } champs @@ -68,7 +84,7 @@ impl DataSource for MSDataSource { let rep = client .get( format!( - "https://www.metasrc.com/5v5/champion/{}/{}", + "https://www.metasrc.com/lol/build/{}/{}", champ.id.to_lowercase(), positions[0].to_lowercase() ) @@ -77,18 +93,19 @@ impl DataSource for MSDataSource { .call(); if let Ok(p) = rep { let page = p.into_string().unwrap(); - let mut pos = page.find("Patch ").unwrap(); - let patch = &page[pos + 6..pos + 11]; + let patch = find_next_number(&page[pos..]).to_string(); - pos = page.find("Win Rate:").unwrap(); - let win_rate: f32 = page[pos + 26..pos + 31].parse().unwrap(); + pos = page.find("Win").unwrap(); + let win_rate: f32 = find_next_number(&page[pos..]); pos = page.find("KDA:").unwrap(); - let kda: f32 = page[pos + 21..pos + 25].parse().unwrap(); + let kda: f32 = find_next_number(&page[pos..]); + + pos = page.find("Games:").unwrap(); + let games: u32 = find_next_number(&page[pos..]) as u32; let mut items = vec![]; - let mut pos: Option = page.find("/item/"); while let Some(mut p) = pos { p += 6; @@ -109,9 +126,9 @@ impl DataSource for MSDataSource { vec![self.make_item_set(items, "Set".to_owned())], Stat { win_rate, - games: 1, + games, kda, - patch: patch.to_owned(), + patch, }, )); }