refactor: centralize HTTP client creation with dynamic user agent
This commit is contained in:
parent
1e1f89ddc0
commit
03d4537743
6 changed files with 101 additions and 111 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -75,6 +75,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
name = "cggitem_sets"
|
name = "cggitem_sets"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
"logsy",
|
"logsy",
|
||||||
|
|
|
@ -6,6 +6,7 @@ version = "1.0.0"
|
||||||
include = ["src/**/*"]
|
include = ["src/**/*"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
chrono = {version = "0.4.41", features = ["std"], default-features = false}
|
||||||
indexmap = {version = "2.2", features = ["serde", "rayon"]}
|
indexmap = {version = "2.2", features = ["serde", "rayon"]}
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
logsy = "1.0.1"
|
logsy = "1.0.1"
|
||||||
|
|
|
@ -44,11 +44,7 @@ pub trait DataSource {
|
||||||
|
|
||||||
fn get_timeout(&self) -> u64;
|
fn get_timeout(&self) -> u64;
|
||||||
|
|
||||||
fn get_champs_with_positions(
|
fn get_champs_with_positions(&self, champion: &Champion) -> IndexMap<u32, Vec<String>>;
|
||||||
&self,
|
|
||||||
client: &ureq::Agent,
|
|
||||||
champion: &Champion,
|
|
||||||
) -> IndexMap<u32, Vec<String>>;
|
|
||||||
|
|
||||||
fn make_item_set(&self, items: Vec<&str>, label: String) -> Value {
|
fn make_item_set(&self, items: Vec<&str>, label: String) -> Value {
|
||||||
json!({
|
json!({
|
||||||
|
@ -61,7 +57,6 @@ pub trait DataSource {
|
||||||
&self,
|
&self,
|
||||||
champ: &ChampInfo,
|
champ: &ChampInfo,
|
||||||
positions: &[String],
|
positions: &[String],
|
||||||
client: &ureq::Agent,
|
|
||||||
) -> Vec<(String, Vec<Value>, Stat)>;
|
) -> Vec<(String, Vec<Value>, Stat)>;
|
||||||
|
|
||||||
fn write_item_set(
|
fn write_item_set(
|
||||||
|
@ -69,7 +64,6 @@ pub trait DataSource {
|
||||||
champ: &ChampInfo,
|
champ: &ChampInfo,
|
||||||
positions: &[String],
|
positions: &[String],
|
||||||
path: &Path,
|
path: &Path,
|
||||||
client: &ureq::Agent,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
info!(
|
info!(
|
||||||
"{}: Retrieving data for {} at {}",
|
"{}: Retrieving data for {} at {}",
|
||||||
|
@ -77,7 +71,7 @@ pub trait DataSource {
|
||||||
champ.name,
|
champ.name,
|
||||||
positions.join(", ")
|
positions.join(", ")
|
||||||
);
|
);
|
||||||
let data = self.get_champ_data_with_win_pourcentage(champ, positions, client);
|
let data = self.get_champ_data_with_win_pourcentage(champ, positions);
|
||||||
|
|
||||||
let mut missing_roles = vec![];
|
let mut missing_roles = vec![];
|
||||||
for pos in positions {
|
for pos in positions {
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
use crate::ChampInfo;
|
use crate::ChampInfo;
|
||||||
use crate::Champion as ChampionLoL;
|
use crate::Champion as ChampionLoL;
|
||||||
use crate::USER_AGENT_VALUE;
|
|
||||||
use crate::data_source::{Build, DataSource, Item, Stat};
|
use crate::data_source::{Build, DataSource, Item, Stat};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use log::error;
|
use log::error;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
use std::time::Duration;
|
|
||||||
use ureq::Agent;
|
|
||||||
|
|
||||||
pub struct KBDataSource {
|
pub struct KBDataSource {
|
||||||
|
client: ureq::Agent,
|
||||||
token: Option<String>,
|
token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,39 +115,38 @@ struct Summoner {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// It will be better to use Result...
|
|
||||||
fn get_auth_token() -> Option<String> {
|
|
||||||
let client: Agent = Agent::config_builder()
|
|
||||||
.user_agent(USER_AGENT_VALUE)
|
|
||||||
.timeout_global(Some(Duration::from_secs(10)))
|
|
||||||
.build()
|
|
||||||
.into();
|
|
||||||
let mut bundle = match client.get("https://koreanbuilds.net/bundle.js").call() {
|
|
||||||
Ok(mut resp) => match resp.body_mut().read_to_string() {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(_) => return None,
|
|
||||||
},
|
|
||||||
Err(_) => return None,
|
|
||||||
};
|
|
||||||
let auth_position = bundle.find("Authorization")?;
|
|
||||||
bundle = bundle[(auth_position + 13)..].to_string();
|
|
||||||
let q_position = bundle.find('"')?;
|
|
||||||
bundle = bundle[(q_position + 1)..].to_string();
|
|
||||||
bundle
|
|
||||||
.find('"')
|
|
||||||
.map(|position| bundle[..position].to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KBDataSource {
|
impl KBDataSource {
|
||||||
pub fn new() -> KBDataSource {
|
pub fn new(client: &ureq::Agent) -> Self {
|
||||||
Self {
|
Self {
|
||||||
token: get_auth_token(),
|
client: client.clone(),
|
||||||
|
token: Self::fetch_auth_token(client),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_champion_response(&self, client: &ureq::Agent) -> Option<ChampionResponse> {
|
fn fetch_auth_token(client: &ureq::Agent) -> Option<String> {
|
||||||
|
let resp = client.get("https://koreanbuilds.net/bundle.js").call();
|
||||||
|
if let Ok(mut resp) = resp {
|
||||||
|
if let Ok(bundle) = resp.body_mut().read_to_string() {
|
||||||
|
if let Some(token) = Self::extract_token(&bundle) {
|
||||||
|
return Some(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_token(bundle: &str) -> Option<String> {
|
||||||
|
let auth_marker = "Authorization";
|
||||||
|
let start = bundle.find(auth_marker)? + auth_marker.len();
|
||||||
|
let after_marker = bundle[start..].find('"')? + start + 1;
|
||||||
|
let end = bundle[after_marker..].find('"')? + after_marker;
|
||||||
|
Some(bundle[after_marker..end].to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_champion_response(&self) -> Option<ChampionResponse> {
|
||||||
if let Some(token) = &self.token {
|
if let Some(token) = &self.token {
|
||||||
return match client
|
return match self
|
||||||
|
.client
|
||||||
.get("https://api.koreanbuilds.net/champions?patchid=-1")
|
.get("https://api.koreanbuilds.net/champions?patchid=-1")
|
||||||
.header("Accept", "application/json")
|
.header("Accept", "application/json")
|
||||||
.header("Authorization", token.as_str())
|
.header("Authorization", token.as_str())
|
||||||
|
@ -307,13 +304,9 @@ impl DataSource for KBDataSource {
|
||||||
300
|
300
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_champs_with_positions(
|
fn get_champs_with_positions(&self, _champion: &ChampionLoL) -> IndexMap<u32, Vec<String>> {
|
||||||
&self,
|
|
||||||
client: &ureq::Agent,
|
|
||||||
_champion: &ChampionLoL,
|
|
||||||
) -> IndexMap<u32, Vec<String>> {
|
|
||||||
let mut champions = IndexMap::new();
|
let mut champions = IndexMap::new();
|
||||||
let data: ChampionResponse = match self.get_champion_response(client) {
|
let data: ChampionResponse = match self.get_champion_response() {
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
None => {
|
None => {
|
||||||
return champions;
|
return champions;
|
||||||
|
@ -329,11 +322,11 @@ impl DataSource for KBDataSource {
|
||||||
&self,
|
&self,
|
||||||
champ: &ChampInfo,
|
champ: &ChampInfo,
|
||||||
position: &[String],
|
position: &[String],
|
||||||
client: &ureq::Agent,
|
|
||||||
) -> Vec<(String, Vec<Value>, Stat)> {
|
) -> Vec<(String, Vec<Value>, Stat)> {
|
||||||
let mut champ_data = vec![];
|
let mut champ_data = vec![];
|
||||||
if let Some(token) = &self.token {
|
if let Some(token) = &self.token {
|
||||||
let data: BuildResponse = match client
|
let data: BuildResponse = match self
|
||||||
|
.client
|
||||||
.get(&format!(
|
.get(&format!(
|
||||||
"https://api.koreanbuilds.net/builds?chmpname={}&patchid=-2&position=COMPOSITE",
|
"https://api.koreanbuilds.net/builds?chmpname={}&patchid=-2&position=COMPOSITE",
|
||||||
champ.name
|
champ.name
|
||||||
|
@ -371,10 +364,15 @@ impl DataSource for KBDataSource {
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::create_http_client;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
static DATASOURCE: LazyLock<KBDataSource> =
|
||||||
|
LazyLock::new(|| KBDataSource::new(&create_http_client()));
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_auth_token() {
|
fn test_get_auth_token() {
|
||||||
match get_auth_token() {
|
match &DATASOURCE.token {
|
||||||
Some(token) => assert!(token.len() > 0),
|
Some(token) => assert!(token.len() > 0),
|
||||||
None => assert!(false),
|
None => assert!(false),
|
||||||
};
|
};
|
||||||
|
@ -382,37 +380,22 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_champs_with_positions_and_patch() {
|
fn test_get_champs_with_positions_and_patch() {
|
||||||
let client = ureq::Agent::config_builder()
|
|
||||||
.user_agent(USER_AGENT_VALUE)
|
|
||||||
.timeout_global(Some(Duration::from_secs(10)))
|
|
||||||
.build()
|
|
||||||
.into();
|
|
||||||
let datasource = KBDataSource::new();
|
|
||||||
let champion = ChampionLoL {
|
let champion = ChampionLoL {
|
||||||
data: IndexMap::new(),
|
data: IndexMap::new(),
|
||||||
};
|
};
|
||||||
let champs_with_positions = datasource.get_champs_with_positions(&client, &champion);
|
let champs_with_positions = DATASOURCE.get_champs_with_positions(&champion);
|
||||||
assert!(champs_with_positions.len() > 0);
|
assert!(champs_with_positions.len() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_champ_data_with_win_pourcentage() {
|
fn test_get_champ_data_with_win_pourcentage() {
|
||||||
let client = ureq::Agent::config_builder()
|
|
||||||
.user_agent(USER_AGENT_VALUE)
|
|
||||||
.timeout_global(Some(Duration::from_secs(10)))
|
|
||||||
.build()
|
|
||||||
.into();
|
|
||||||
let datasource = KBDataSource::new();
|
|
||||||
let champ = ChampInfo {
|
let champ = ChampInfo {
|
||||||
id: String::from("Annie"),
|
id: String::from("Annie"),
|
||||||
name: String::from("Annie"),
|
name: String::from("Annie"),
|
||||||
key: String::from("1"),
|
key: String::from("1"),
|
||||||
};
|
};
|
||||||
let result = datasource.get_champ_data_with_win_pourcentage(
|
let result =
|
||||||
&champ,
|
DATASOURCE.get_champ_data_with_win_pourcentage(&champ, &vec!["MID".to_string()]);
|
||||||
&vec!["MID".to_string()],
|
|
||||||
&client,
|
|
||||||
);
|
|
||||||
assert!(!result.is_empty());
|
assert!(!result.is_empty());
|
||||||
assert!(!result[0].1.is_empty());
|
assert!(!result[0].1.is_empty());
|
||||||
assert!(result[0].2.win_rate > 0.);
|
assert!(result[0].2.win_rate > 0.);
|
||||||
|
|
78
src/main.rs
78
src/main.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use chrono::{Datelike, Local, NaiveDate};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
@ -10,7 +11,6 @@ use std::io;
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::ops::Deref;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::{fs, thread, time};
|
use std::{fs, thread, time};
|
||||||
|
@ -44,8 +44,6 @@ pub struct ChampInfo {
|
||||||
key: String,
|
key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
const USER_AGENT_VALUE: &str =
|
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:139.0) Gecko/20100101 Firefox/139.0";
|
|
||||||
const DEFAULT_LOL_CHAMPS_DIR: &str = "./champs";
|
const DEFAULT_LOL_CHAMPS_DIR: &str = "./champs";
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const REG_KEY_LOL_RADS: &str = r"SOFTWARE\WOW6432Node\Riot Games\RADS";
|
const REG_KEY_LOL_RADS: &str = r"SOFTWARE\WOW6432Node\Riot Games\RADS";
|
||||||
|
@ -76,11 +74,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
};
|
};
|
||||||
info!("LoL Champs Folder: {}", lol_champs_dir.display());
|
info!("LoL Champs Folder: {}", lol_champs_dir.display());
|
||||||
|
|
||||||
let client: Agent = Agent::config_builder()
|
let client: Agent = create_http_client();
|
||||||
.user_agent(USER_AGENT_VALUE)
|
|
||||||
.timeout_global(Some(Duration::from_secs(10)))
|
|
||||||
.build()
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let realm: Realm = client
|
let realm: Realm = client
|
||||||
.get("https://ddragon.leagueoflegends.com/realms/euw.json")
|
.get("https://ddragon.leagueoflegends.com/realms/euw.json")
|
||||||
|
@ -98,11 +92,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.read_json()?;
|
.read_json()?;
|
||||||
info!("LoL numbers of champs: {}", champion.data.len());
|
info!("LoL numbers of champs: {}", champion.data.len());
|
||||||
|
|
||||||
let data_sources: Vec<Box<dyn DataSource + Sync + Send>> =
|
let data_sources: Vec<Box<dyn DataSource + Sync + Send>> = vec![
|
||||||
vec![Box::new(KBDataSource::new()), Box::new(MSDataSource)];
|
Box::new(KBDataSource::new(&client)),
|
||||||
|
Box::new(MSDataSource::new(&client)),
|
||||||
|
];
|
||||||
data_sources.par_iter().for_each(|data_source| {
|
data_sources.par_iter().for_each(|data_source| {
|
||||||
let init = Instant::now();
|
let init = Instant::now();
|
||||||
execute_data_source(data_source.deref(), &client, &champion, &lol_champs_dir);
|
execute_data_source(&**data_source, &champion, &lol_champs_dir);
|
||||||
info!(
|
info!(
|
||||||
"{}: done in {}s",
|
"{}: done in {}s",
|
||||||
data_source.get_alias(),
|
data_source.get_alias(),
|
||||||
|
@ -123,11 +119,10 @@ fn get_champ_from_key(champs: &Champion, key: u32) -> Option<String> {
|
||||||
|
|
||||||
fn execute_data_source(
|
fn execute_data_source(
|
||||||
data_source: &(dyn DataSource + Sync + Send),
|
data_source: &(dyn DataSource + Sync + Send),
|
||||||
client: &ureq::Agent,
|
|
||||||
champion: &Champion,
|
champion: &Champion,
|
||||||
lol_champs_dir: &Path,
|
lol_champs_dir: &Path,
|
||||||
) {
|
) {
|
||||||
let champs = data_source.get_champs_with_positions(client, champion);
|
let champs = data_source.get_champs_with_positions(champion);
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"{} numbers of champs: {}",
|
"{} numbers of champs: {}",
|
||||||
|
@ -135,35 +130,22 @@ fn execute_data_source(
|
||||||
champs.len()
|
champs.len()
|
||||||
);
|
);
|
||||||
|
|
||||||
if data_source.get_timeout() == 0 {
|
let process = |(id, positions): (&u32, &Vec<String>)| {
|
||||||
champs.par_iter().for_each(|(id, positions)| {
|
get_and_write_item_set(data_source, champion, lol_champs_dir, *id, positions);
|
||||||
get_and_write_item_set(
|
if data_source.get_timeout() > 0 {
|
||||||
data_source,
|
|
||||||
client,
|
|
||||||
champion,
|
|
||||||
lol_champs_dir,
|
|
||||||
*id,
|
|
||||||
positions,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
champs.iter().for_each(|(id, positions)| {
|
|
||||||
get_and_write_item_set(
|
|
||||||
data_source,
|
|
||||||
client,
|
|
||||||
champion,
|
|
||||||
lol_champs_dir,
|
|
||||||
*id,
|
|
||||||
positions,
|
|
||||||
);
|
|
||||||
thread::sleep(Duration::from_millis(data_source.get_timeout()));
|
thread::sleep(Duration::from_millis(data_source.get_timeout()));
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if data_source.get_timeout() == 0 {
|
||||||
|
champs.par_iter().for_each(process);
|
||||||
|
} else {
|
||||||
|
champs.iter().for_each(process);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_and_write_item_set(
|
fn get_and_write_item_set(
|
||||||
data_source: &(dyn DataSource + Sync + Send),
|
data_source: &(dyn DataSource + Sync + Send),
|
||||||
client: &ureq::Agent,
|
|
||||||
champion: &Champion,
|
champion: &Champion,
|
||||||
lol_champs_dir: &Path,
|
lol_champs_dir: &Path,
|
||||||
id: u32,
|
id: u32,
|
||||||
|
@ -176,7 +158,7 @@ fn get_and_write_item_set(
|
||||||
} else {
|
} else {
|
||||||
let path = lol_champs_dir.join(&champ_id).join("Recommended");
|
let path = lol_champs_dir.join(&champ_id).join("Recommended");
|
||||||
match fs::create_dir_all(&path) {
|
match fs::create_dir_all(&path) {
|
||||||
Ok(_) => match data_source.write_item_set(champ, positions, &path, client) {
|
Ok(_) => match data_source.write_item_set(champ, positions, &path) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => error!(
|
Err(e) => error!(
|
||||||
"{}: Failed to write item set for {} at {}: {}",
|
"{}: Failed to write item set for {} at {}: {}",
|
||||||
|
@ -197,6 +179,28 @@ fn get_and_write_item_set(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_http_client() -> Agent {
|
||||||
|
Agent::config_builder()
|
||||||
|
.user_agent(get_browser_user_agent())
|
||||||
|
.timeout_global(Some(Duration::from_secs(10)))
|
||||||
|
.build()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_browser_user_agent() -> String {
|
||||||
|
let base_version = 125;
|
||||||
|
let start_date = NaiveDate::from_ymd_opt(2024, 4, 16).unwrap();
|
||||||
|
let now = Local::now().naive_local().date();
|
||||||
|
|
||||||
|
let months_between =
|
||||||
|
(now.year() - start_date.year()) * 12 + (now.month() as i32 - start_date.month() as i32);
|
||||||
|
let version = base_version + months_between;
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:{version}.0) Gecko/20100101 Firefox/{version}.0"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn lol_champ_dir() -> Result<PathBuf, Error> {
|
fn lol_champ_dir() -> Result<PathBuf, Error> {
|
||||||
let hklm = RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE);
|
let hklm = RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE);
|
||||||
|
|
|
@ -8,7 +8,9 @@ use crate::ChampInfo;
|
||||||
use crate::Champion;
|
use crate::Champion;
|
||||||
use crate::data_source::{DataSource, Stat};
|
use crate::data_source::{DataSource, Stat};
|
||||||
|
|
||||||
pub struct MSDataSource;
|
pub struct MSDataSource {
|
||||||
|
client: ureq::Agent,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct MSChampion {
|
struct MSChampion {
|
||||||
|
@ -38,6 +40,14 @@ fn find_next_number(rest: &str) -> f32 {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MSDataSource {
|
||||||
|
pub fn new(client: &ureq::Agent) -> Self {
|
||||||
|
MSDataSource {
|
||||||
|
client: client.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DataSource for MSDataSource {
|
impl DataSource for MSDataSource {
|
||||||
fn get_alias(&self) -> &str {
|
fn get_alias(&self) -> &str {
|
||||||
"MS"
|
"MS"
|
||||||
|
@ -47,14 +57,11 @@ impl DataSource for MSDataSource {
|
||||||
300
|
300
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_champs_with_positions(
|
fn get_champs_with_positions(&self, champion: &Champion) -> IndexMap<u32, Vec<String>> {
|
||||||
&self,
|
|
||||||
client: &ureq::Agent,
|
|
||||||
champion: &Champion,
|
|
||||||
) -> IndexMap<u32, Vec<String>> {
|
|
||||||
let mut champs = IndexMap::new();
|
let mut champs = IndexMap::new();
|
||||||
|
|
||||||
let champions: Vec<MSChampion> = match client
|
let champions: Vec<MSChampion> = match self
|
||||||
|
.client
|
||||||
.get("https://www.metasrc.com/lol/search/lol")
|
.get("https://www.metasrc.com/lol/search/lol")
|
||||||
.call()
|
.call()
|
||||||
.and_then(|mut resp| resp.body_mut().read_json())
|
.and_then(|mut resp| resp.body_mut().read_json())
|
||||||
|
@ -85,11 +92,11 @@ impl DataSource for MSDataSource {
|
||||||
&self,
|
&self,
|
||||||
champ: &ChampInfo,
|
champ: &ChampInfo,
|
||||||
positions: &[String],
|
positions: &[String],
|
||||||
client: &ureq::Agent,
|
|
||||||
) -> Vec<(String, Vec<Value>, Stat)> {
|
) -> Vec<(String, Vec<Value>, Stat)> {
|
||||||
let mut builds = vec![];
|
let mut builds = vec![];
|
||||||
|
|
||||||
let rep = client
|
let rep = self
|
||||||
|
.client
|
||||||
.get(
|
.get(
|
||||||
format!(
|
format!(
|
||||||
"https://www.metasrc.com/lol/build/{}/{}",
|
"https://www.metasrc.com/lol/build/{}/{}",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue