From 8c2cf6478428bc576d2b438cd6c1e4afd69aca9d Mon Sep 17 00:00:00 2001 From: Mingwei Samuel Date: Thu, 7 Nov 2019 16:06:01 -0800 Subject: [PATCH] Update return Option only if x-nullable-404 --- README.md | 5 +-- src/endpoints.rs | 78 +++++++++++++++++------------------ src/error.rs | 3 +- src/req/regional_requester.rs | 42 +++++++++++-------- src/riot_api.rs | 26 ++++++++---- srcgen/endpoints.rs.dt | 9 ++-- tests/tests_euw.rs | 6 +-- tests/tests_na.rs | 6 +-- tests/tests_tr.rs | 5 +-- 9 files changed, 101 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index 0330d9d..eea5ffc 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ rt.block_on(async { let summoner = riot_api.summoner_v4() .get_by_summoner_name(Region::NA, "잘못").await .expect("Get summoner failed.") - .expect("Summoner not found."); + .expect("There is no summoner with that name."); // Print summoner name. println!("{} Champion Masteries:", summoner.name); @@ -46,8 +46,7 @@ rt.block_on(async { // Get champion mastery data. let masteries = riot_api.champion_mastery_v4() .get_all_champion_masteries(Region::NA, &summoner.id).await - .expect("Get champion masteries failed.") - .unwrap(); + .expect("Get champion masteries failed."); // Print champioon masteries. for (i, mastery) in masteries[..10].iter().enumerate() { diff --git a/src/endpoints.rs b/src/endpoints.rs index 17a00bc..5b8bcc1 100644 --- a/src/endpoints.rs +++ b/src/endpoints.rs @@ -137,7 +137,7 @@ impl<'a> ChampionMasteryV4<'a> { /// * `region` - Region to query. /// * `encryptedSummonerId` - Summoner ID associated with the player pub fn get_all_champion_masteries(&self, region: Region, encrypted_summoner_id: &str) - -> impl Future>>> + 'a + -> impl Future>> + 'a { let path_string = format!("/lol/champion-mastery/v4/champion-masteries/by-summoner/{}", encrypted_summoner_id); self.base.get::>("champion-mastery-v4.getAllChampionMasteries", region.into(), path_string, None) @@ -154,7 +154,7 @@ impl<'a> ChampionMasteryV4<'a> { -> impl Future>> + 'a { let path_string = format!("/lol/champion-mastery/v4/champion-masteries/by-summoner/{}/by-champion/{}", encrypted_summoner_id, champion_id); - self.base.get::("champion-mastery-v4.getChampionMastery", region.into(), path_string, None) + self.base.get_optional::("champion-mastery-v4.getChampionMastery", region.into(), path_string, None) } /// Get a player's total champion mastery score, which is the sum of individual champion mastery levels. @@ -164,7 +164,7 @@ impl<'a> ChampionMasteryV4<'a> { /// * `region` - Region to query. /// * `encryptedSummonerId` - Summoner ID associated with the player pub fn get_champion_mastery_score(&self, region: Region, encrypted_summoner_id: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/champion-mastery/v4/scores/by-summoner/{}", encrypted_summoner_id); self.base.get::("champion-mastery-v4.getChampionMasteryScore", region.into(), path_string, None) @@ -185,7 +185,7 @@ impl<'a> ChampionV3<'a> { /// # Parameters /// * `region` - Region to query. pub fn get_champion_info(&self, region: Region) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = "/lol/platform/v3/champion-rotations".to_owned(); self.base.get::("champion-v3.getChampionInfo", region.into(), path_string, None) @@ -210,7 +210,7 @@ impl<'a> LeagueExpV4<'a> { /// * `division` /// * `page` (optional) - Starts with page 1. pub fn get_league_entries(&self, region: Region, queue: crate::consts::QueueType, tier: crate::consts::Tier, division: crate::consts::Division, page: Option) - -> impl Future>>> + 'a + -> impl Future>> + 'a { let mut query_params = Serializer::new(String::new()); if let Some(page) = page { query_params.append_pair("page", &*page.to_string()); }; @@ -235,7 +235,7 @@ impl<'a> LeagueV4<'a> { /// * `region` - Region to query. /// * `queue` pub fn get_challenger_league(&self, region: Region, queue: crate::consts::QueueType) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/league/v4/challengerleagues/by-queue/{}", queue); self.base.get::("league-v4.getChallengerLeague", region.into(), path_string, None) @@ -248,7 +248,7 @@ impl<'a> LeagueV4<'a> { /// * `region` - Region to query. /// * `encryptedSummonerId` pub fn get_league_entries_for_summoner(&self, region: Region, encrypted_summoner_id: &str) - -> impl Future>>> + 'a + -> impl Future>> + 'a { let path_string = format!("/lol/league/v4/entries/by-summoner/{}", encrypted_summoner_id); self.base.get::>("league-v4.getLeagueEntriesForSummoner", region.into(), path_string, None) @@ -264,7 +264,7 @@ impl<'a> LeagueV4<'a> { /// * `queue` - Note that the queue value must be a valid ranked queue. /// * `page` (optional) - Starts with page 1. pub fn get_league_entries(&self, region: Region, queue: crate::consts::QueueType, tier: crate::consts::Tier, division: crate::consts::Division, page: Option) - -> impl Future>>> + 'a + -> impl Future>> + 'a { let mut query_params = Serializer::new(String::new()); if let Some(page) = page { query_params.append_pair("page", &*page.to_string()); }; @@ -280,7 +280,7 @@ impl<'a> LeagueV4<'a> { /// * `region` - Region to query. /// * `queue` pub fn get_grandmaster_league(&self, region: Region, queue: crate::consts::QueueType) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/league/v4/grandmasterleagues/by-queue/{}", queue); self.base.get::("league-v4.getGrandmasterLeague", region.into(), path_string, None) @@ -296,7 +296,7 @@ impl<'a> LeagueV4<'a> { -> impl Future>> + 'a { let path_string = format!("/lol/league/v4/leagues/{}", league_id); - self.base.get::("league-v4.getLeagueById", region.into(), path_string, None) + self.base.get_optional::("league-v4.getLeagueById", region.into(), path_string, None) } /// Get the master league for given queue. @@ -306,7 +306,7 @@ impl<'a> LeagueV4<'a> { /// * `region` - Region to query. /// * `queue` pub fn get_master_league(&self, region: Region, queue: crate::consts::QueueType) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/league/v4/masterleagues/by-queue/{}", queue); self.base.get::("league-v4.getMasterLeague", region.into(), path_string, None) @@ -329,7 +329,7 @@ impl<'a> LolStatusV3<'a> { /// # Parameters /// * `region` - Region to query. pub fn get_shard_data(&self, region: Region) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = "/lol/status/v3/shard-data".to_owned(); self.base.get::("lol-status-v3.getShardData", region.into(), path_string, None) @@ -351,7 +351,7 @@ impl<'a> MatchV4<'a> { /// * `region` - Region to query. /// * `tournamentCode` - The tournament code. pub fn get_match_ids_by_tournament_code(&self, region: Region, tournament_code: &str) - -> impl Future>>> + 'a + -> impl Future>> + 'a { let path_string = format!("/lol/match/v4/matches/by-tournament-code/{}/ids", tournament_code); self.base.get::>("match-v4.getMatchIdsByTournamentCode", region.into(), path_string, None) @@ -367,7 +367,7 @@ impl<'a> MatchV4<'a> { -> impl Future>> + 'a { let path_string = format!("/lol/match/v4/matches/{}", match_id); - self.base.get::("match-v4.getMatch", region.into(), path_string, None) + self.base.get_optional::("match-v4.getMatch", region.into(), path_string, None) } /// Get match by match ID and tournament code. @@ -378,7 +378,7 @@ impl<'a> MatchV4<'a> { /// * `tournamentCode` - The tournament code. /// * `matchId` - The match ID. pub fn get_match_by_tournament_code(&self, region: Region, match_id: i64, tournament_code: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/match/v4/matches/{}/by-tournament-code/{}", match_id, tournament_code); self.base.get::("match-v4.getMatchByTournamentCode", region.into(), path_string, None) @@ -416,7 +416,7 @@ impl<'a> MatchV4<'a> { if let Some(season) = season { query_params.extend_pairs(season.iter().map(|w| ("season", Into::::into(*w).to_string()))); }; let query_string = query_params.finish(); let path_string = format!("/lol/match/v4/matchlists/by-account/{}", encrypted_account_id); - self.base.get::("match-v4.getMatchlist", region.into(), path_string, Some(query_string)) + self.base.get_optional::("match-v4.getMatchlist", region.into(), path_string, Some(query_string)) } /// Get match timeline by match ID. @@ -431,7 +431,7 @@ impl<'a> MatchV4<'a> { -> impl Future>> + 'a { let path_string = format!("/lol/match/v4/timelines/by-match/{}", match_id); - self.base.get::("match-v4.getMatchTimeline", region.into(), path_string, None) + self.base.get_optional::("match-v4.getMatchTimeline", region.into(), path_string, None) } } @@ -453,7 +453,7 @@ impl<'a> SpectatorV4<'a> { -> impl Future>> + 'a { let path_string = format!("/lol/spectator/v4/active-games/by-summoner/{}", encrypted_summoner_id); - self.base.get::("spectator-v4.getCurrentGameInfoBySummoner", region.into(), path_string, None) + self.base.get_optional::("spectator-v4.getCurrentGameInfoBySummoner", region.into(), path_string, None) } /// Get list of featured games. @@ -462,7 +462,7 @@ impl<'a> SpectatorV4<'a> { /// # Parameters /// * `region` - Region to query. pub fn get_featured_games(&self, region: Region) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = "/lol/spectator/v4/featured-games".to_owned(); self.base.get::("spectator-v4.getFeaturedGames", region.into(), path_string, None) @@ -484,7 +484,7 @@ impl<'a> SummonerV4<'a> { /// * `region` - Region to query. /// * `encryptedAccountId` pub fn get_by_account_id(&self, region: Region, encrypted_account_id: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/summoner/v4/summoners/by-account/{}", encrypted_account_id); self.base.get::("summoner-v4.getByAccountId", region.into(), path_string, None) @@ -500,7 +500,7 @@ impl<'a> SummonerV4<'a> { -> impl Future>> + 'a { let path_string = format!("/lol/summoner/v4/summoners/by-name/{}", summoner_name); - self.base.get::("summoner-v4.getBySummonerName", region.into(), path_string, None) + self.base.get_optional::("summoner-v4.getBySummonerName", region.into(), path_string, None) } /// Get a summoner by PUUID. @@ -510,7 +510,7 @@ impl<'a> SummonerV4<'a> { /// * `region` - Region to query. /// * `encryptedPUUID` - Summoner ID pub fn get_by_puuid(&self, region: Region, encrypted_puuid: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/summoner/v4/summoners/by-puuid/{}", encrypted_puuid); self.base.get::("summoner-v4.getByPUUID", region.into(), path_string, None) @@ -523,7 +523,7 @@ impl<'a> SummonerV4<'a> { /// * `region` - Region to query. /// * `encryptedSummonerId` - Summoner ID pub fn get_by_summoner_id(&self, region: Region, encrypted_summoner_id: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/summoner/v4/summoners/{}", encrypted_summoner_id); self.base.get::("summoner-v4.getBySummonerId", region.into(), path_string, None) @@ -544,7 +544,7 @@ impl<'a> TftLeagueV1<'a> { /// # Parameters /// * `region` - Region to query. pub fn get_challenger_league(&self, region: Region) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = "/tft/league/v1/challenger".to_owned(); self.base.get::("tft-league-v1.getChallengerLeague", region.into(), path_string, None) @@ -557,7 +557,7 @@ impl<'a> TftLeagueV1<'a> { /// * `region` - Region to query. /// * `encryptedSummonerId` pub fn get_league_entries_for_summoner(&self, region: Region, encrypted_summoner_id: &str) - -> impl Future>>> + 'a + -> impl Future>> + 'a { let path_string = format!("/tft/league/v1/entries/by-summoner/{}", encrypted_summoner_id); self.base.get::>("tft-league-v1.getLeagueEntriesForSummoner", region.into(), path_string, None) @@ -572,7 +572,7 @@ impl<'a> TftLeagueV1<'a> { /// * `division` /// * `page` (optional) - Starts with page 1. pub fn get_league_entries(&self, region: Region, tier: &str, division: &str, page: Option) - -> impl Future>>> + 'a + -> impl Future>> + 'a { let mut query_params = Serializer::new(String::new()); if let Some(page) = page { query_params.append_pair("page", &*page.to_string()); }; @@ -587,7 +587,7 @@ impl<'a> TftLeagueV1<'a> { /// # Parameters /// * `region` - Region to query. pub fn get_grandmaster_league(&self, region: Region) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = "/tft/league/v1/grandmaster".to_owned(); self.base.get::("tft-league-v1.getGrandmasterLeague", region.into(), path_string, None) @@ -600,7 +600,7 @@ impl<'a> TftLeagueV1<'a> { /// * `region` - Region to query. /// * `leagueId` - The UUID of the league. pub fn get_league_by_id(&self, region: Region, league_id: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/tft/league/v1/leagues/{}", league_id); self.base.get::("tft-league-v1.getLeagueById", region.into(), path_string, None) @@ -612,7 +612,7 @@ impl<'a> TftLeagueV1<'a> { /// # Parameters /// * `region` - Region to query. pub fn get_master_league(&self, region: Region) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = "/tft/league/v1/master".to_owned(); self.base.get::("tft-league-v1.getMasterLeague", region.into(), path_string, None) @@ -634,7 +634,7 @@ impl<'a> TftMatchV1<'a> { /// * `region` - Region to query. /// * `encryptedPUUID` (optional) pub fn get_match_ids_by_puuid(&self, region: Region, encrypted_puuid: &str) - -> impl Future>>> + 'a + -> impl Future>> + 'a { let path_string = format!("/tft/match/v1/matches/by-puuid/{}/ids", encrypted_puuid); self.base.get::>("tft-match-v1.getMatchIdsByPUUID", region.into(), path_string, None) @@ -647,7 +647,7 @@ impl<'a> TftMatchV1<'a> { /// * `region` - Region to query. /// * `matchId` pub fn get_match(&self, region: Region, match_id: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/tft/match/v1/matches/{}", match_id); self.base.get::("tft-match-v1.getMatch", region.into(), path_string, None) @@ -669,7 +669,7 @@ impl<'a> TftSummonerV1<'a> { /// * `region` - Region to query. /// * `encryptedAccountId` pub fn get_by_account_id(&self, region: Region, encrypted_account_id: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/tft/summoner/v1/summoners/by-account/{}", encrypted_account_id); self.base.get::("tft-summoner-v1.getByAccountId", region.into(), path_string, None) @@ -682,7 +682,7 @@ impl<'a> TftSummonerV1<'a> { /// * `region` - Region to query. /// * `summonerName` - Summoner Name pub fn get_by_summoner_name(&self, region: Region, summoner_name: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/tft/summoner/v1/summoners/by-name/{}", summoner_name); self.base.get::("tft-summoner-v1.getBySummonerName", region.into(), path_string, None) @@ -695,7 +695,7 @@ impl<'a> TftSummonerV1<'a> { /// * `region` - Region to query. /// * `encryptedPUUID` - Summoner ID pub fn get_by_puuid(&self, region: Region, encrypted_puuid: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/tft/summoner/v1/summoners/by-puuid/{}", encrypted_puuid); self.base.get::("tft-summoner-v1.getByPUUID", region.into(), path_string, None) @@ -708,7 +708,7 @@ impl<'a> TftSummonerV1<'a> { /// * `region` - Region to query. /// * `encryptedSummonerId` - Summoner ID pub fn get_by_summoner_id(&self, region: Region, encrypted_summoner_id: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/tft/summoner/v1/summoners/{}", encrypted_summoner_id); self.base.get::("tft-summoner-v1.getBySummonerId", region.into(), path_string, None) @@ -730,7 +730,7 @@ impl<'a> ThirdPartyCodeV4<'a> { /// * `region` - Region to query. /// * `encryptedSummonerId` pub fn get_third_party_code_by_summoner_id(&self, region: Region, encrypted_summoner_id: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/platform/v4/third-party-code/by-summoner/{}", encrypted_summoner_id); self.base.get::("third-party-code-v4.getThirdPartyCodeBySummonerId", region.into(), path_string, None) @@ -752,7 +752,7 @@ impl<'a> TournamentStubV4<'a> { /// * `region` - Region to query. /// * `tournamentCode` - The short code to look up lobby events for pub fn get_lobby_events_by_code(&self, region: Region, tournament_code: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/tournament-stub/v4/lobby-events/by-code/{}", tournament_code); self.base.get::("tournament-stub-v4.getLobbyEventsByCode", region.into(), path_string, None) @@ -774,7 +774,7 @@ impl<'a> TournamentV4<'a> { /// * `region` - Region to query. /// * `tournamentCode` - The tournament code string. pub fn get_tournament_code(&self, region: Region, tournament_code: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/tournament/v4/codes/{}", tournament_code); self.base.get::("tournament-v4.getTournamentCode", region.into(), path_string, None) @@ -787,7 +787,7 @@ impl<'a> TournamentV4<'a> { /// * `region` - Region to query. /// * `tournamentCode` - The short code to look up lobby events for pub fn get_lobby_events_by_code(&self, region: Region, tournament_code: &str) - -> impl Future>> + 'a + -> impl Future> + 'a { let path_string = format!("/lol/tournament/v4/lobby-events/by-code/{}", tournament_code); self.base.get::("tournament-v4.getLobbyEventsByCode", region.into(), path_string, None) diff --git a/src/error.rs b/src/error.rs index 34ee029..614609b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -37,7 +37,8 @@ impl RiotApiError { pub fn retries(&self) -> u8 { self.retries } - /// The failed response, if the request sent. + /// The failed response, if the request was sent and failed. + /// Will be `None` if JSON parsing failed. pub fn response<'a>(&self) -> Option<&Response> { self.response.as_ref() } diff --git a/src/req/regional_requester.rs b/src/req/regional_requester.rs index e09b327..2c87dff 100644 --- a/src/req/regional_requester.rs +++ b/src/req/regional_requester.rs @@ -24,8 +24,8 @@ impl RegionalRequester { /// Request header name for the Riot API key. const RIOT_KEY_HEADER: &'static str = "X-Riot-Token"; - /// HttpStatus codes that are considered a success, but will return None. - const NONE_STATUS_CODES: [u16; 3] = [ 204, 404, 422 ]; + /// Http status code 404, considered a success but will return None. + const NONE_STATUS_CODE: StatusCode = StatusCode::NOT_FOUND; pub fn new() -> Self { @@ -35,10 +35,29 @@ impl RegionalRequester { } } - pub fn get<'a, T: serde::de::DeserializeOwned>(self: Arc, + pub fn get_optional<'a, T: serde::de::DeserializeOwned>(self: Arc, config: &'a RiotApiConfig, client: &'a Client, method_id: &'static str, region_platform: &'a str, path: String, query: Option) -> impl Future>> + 'a + { + async move { + let response_result = self.get(config, client, + method_id, region_platform, path, query).await; + response_result.map(|value| Some(value)) + .or_else(|e| { + if let Some(response) = e.response() { + if Self::NONE_STATUS_CODE == response.status() { + return Ok(None); + }} + Err(e) + }) + } + } + + pub fn get<'a, T: serde::de::DeserializeOwned>(self: Arc, + config: &'a RiotApiConfig, client: &'a Client, + method_id: &'static str, region_platform: &'a str, path: String, query: Option) + -> impl Future> + 'a { async move { #[cfg(feature = "nightly")] let query = query.as_deref(); @@ -71,21 +90,14 @@ impl RegionalRequester { self.app_rate_limit.on_response(&config, &response); method_rate_limit.on_response(&config, &response); - // Handle response. let status = response.status(); - // Special "none success" cases, return None. - if Self::is_none_status_code(&status) { - log::trace!("Response {} (retried {} times), None result.", status, retries); - break Ok(None); - } // Handle normal success / failure cases. match response.error_for_status_ref() { // Success. - Ok(_) => { + Ok(_response) => { log::trace!("Response {} (retried {} times), parsed result.", status, retries); let value = response.json::().await; - break value.map(|v| Some(v)) - .map_err(|e| RiotApiError::new(e, retries, None)); + break value.map_err(|e| RiotApiError::new(e, retries, None)); }, // Failure, may or may not be retryable. Err(err) => { @@ -95,7 +107,7 @@ impl RegionalRequester { (StatusCode::TOO_MANY_REQUESTS != status && !status.is_server_error()) { - log::debug!("Response {} (retried {} times), returning error.", status, retries); + log::debug!("Response {} (retried {} times), returning.", status, retries); break Err(RiotApiError::new(err, retries, Some(response))); } log::debug!("Response {} (retried {} times), retrying.", status, retries); @@ -106,10 +118,6 @@ impl RegionalRequester { } } } - - fn is_none_status_code(status: &StatusCode) -> bool { - Self::NONE_STATUS_CODES.contains(&status.as_u16()) - } } #[cfg(test)] diff --git a/src/riot_api.rs b/src/riot_api.rs index 4c73c0b..51b6265 100644 --- a/src/riot_api.rs +++ b/src/riot_api.rs @@ -1,4 +1,5 @@ use std::future::Future; +use std::sync::Arc; use log; use reqwest::Client; @@ -12,7 +13,7 @@ use crate::util::InsertOnlyCHashMap; /// /// # Rate Limiting /// -/// The Riot Game API does _dynamic_ rate limiting, meaning that rate limits are +/// The Riot Game API enforces _dynamic_ rate limiting, meaning that rate limits are /// specified in response headers and (hypothetically) could change at any time. /// Riven keeps track of changing rate limits seamlessly, preventing you from /// getting blacklisted. @@ -44,15 +45,26 @@ impl RiotApi { Self::with_config(RiotApiConfig::with_key(api_key)) } - pub fn get<'a, T: serde::de::DeserializeOwned + 'a>(&'a self, + pub fn get_optional<'a, T: serde::de::DeserializeOwned + 'a>(&'a self, method_id: &'static str, region_platform: &'static str, path: String, query: Option) -> impl Future>> + 'a { - self.regional_requesters - .get_or_insert_with(region_platform, || { - log::debug!("Creating requester for region platform {}.", region_platform); - RegionalRequester::new() - }) + self.regional_requester(region_platform) + .get_optional(&self.config, &self.client, method_id, region_platform, path, query) + } + + pub fn get<'a, T: serde::de::DeserializeOwned + 'a>(&'a self, + method_id: &'static str, region_platform: &'static str, path: String, query: Option) + -> impl Future> + 'a + { + self.regional_requester(region_platform) .get(&self.config, &self.client, method_id, region_platform, path, query) } + + fn regional_requester(&self, region_platform: &'static str) -> Arc { + self.regional_requesters.get_or_insert_with(region_platform, || { + log::debug!("Creating requester for region platform {}.", region_platform); + RegionalRequester::new() + }) + } } diff --git a/srcgen/endpoints.rs.dt b/srcgen/endpoints.rs.dt index d08b58e..cc41d7b 100644 --- a/srcgen/endpoints.rs.dt +++ b/srcgen/endpoints.rs.dt @@ -66,7 +66,10 @@ impl<'a> {{= endpoint }}<'a> { let method = dotUtils.changeCase.snakeCase(operationId.slice(operationId.indexOf('.') + 1)); let jsonInfo = get.responses['200'].content['application/json']; - let returnType = dotUtils.stringifyType(jsonInfo.schema, { endpoint, fullpath: false }); + let returnOptional = !!get['x-nullable-404']; + let parseType = dotUtils.stringifyType(jsonInfo.schema, { endpoint, fullpath: false }); + let returnType = returnOptional ? `Option<${parseType}>` : parseType; + /* Cases if not rate limited. */ let rateLimitExcluded = get['x-app-rate-limit-excluded'] ? true : false; @@ -131,7 +134,7 @@ impl<'a> {{= endpoint }}<'a> { } }} pub fn {{= method }}(&self, region: Region{{= argBuilder.join('') }}) - -> impl Future>> + 'a + -> impl Future> + 'a { {{? queryParams.length }} let mut query_params = Serializer::new(String::new()); @@ -146,7 +149,7 @@ impl<'a> {{= endpoint }}<'a> { let query_string = query_params.finish(); {{?}} let path_string = {{= routeArgument }}; - self.base.get::<{{= returnType }}>("{{= operationId }}", region.into(), path_string, {{= queryParams.length ? 'Some(query_string)' : 'None' }}) + self.base.get{{= returnOptional ? '_optional' : '' }}::<{{= parseType }}>("{{= operationId }}", region.into(), path_string, {{= queryParams.length ? 'Some(query_string)' : 'None' }}) } {{ diff --git a/tests/tests_euw.rs b/tests/tests_euw.rs index 8217329..9ed4984 100644 --- a/tests/tests_euw.rs +++ b/tests/tests_euw.rs @@ -15,20 +15,20 @@ async_tests!{ // Champion Mastery tests. championmastery_getscore_ma5tery: async { let p = RIOT_API.champion_mastery_v4().get_champion_mastery_score(Region::EUW, ids::SUMMONER_ID_MA5TERY); - let s = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get ma5tery".to_owned())?; + let s = p.await.map_err(|e| e.to_string())?; rassert!(969 <= s && s <= 1000, "Unexpected ma5tery score: {}.", s); Ok(()) }, championmastery_getall_ma5tery: async { let p = RIOT_API.champion_mastery_v4().get_all_champion_masteries(Region::EUW, ids::SUMMONER_ID_MA5TERY); - let s = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get ma5tery".to_owned())?; + let s = p.await.map_err(|e| e.to_string())?; rassert!(s.len() >= 142, "Expected masteries: {}.", s.len()); Ok(()) }, // // TFT tests. // tftleaguev1_getchallengerleague: async { // let p = RIOT_API.tft_league_v1().get_challenger_league(Region::EUW); - // let l = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get TFT Challenger.".to_owned())?; + // let l = p.await.map_err(|e| e.to_string())?; // rassert!(l.entries.len() > 10, "Expected a few challenger players, got: {}.", l.entries.len()); // Ok(()) // }, diff --git a/tests/tests_na.rs b/tests/tests_na.rs index 91d90f7..879909a 100644 --- a/tests/tests_na.rs +++ b/tests/tests_na.rs @@ -35,7 +35,7 @@ async_tests!{ }, champion_getrotation: async { let p = RIOT_API.champion_v3().get_champion_info(Region::NA); - let d = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get champ info.".to_owned())?; + let d = p.await.map_err(|e| e.to_string())?; let new_len = d.free_champion_ids_for_new_players.len(); let free_len = d.free_champion_ids.len(); let level = d.max_new_player_level; @@ -46,13 +46,13 @@ async_tests!{ }, leagueexp_get: async { let p = RIOT_API.league_exp_v4().get_league_entries(Region::NA, QueueType::RANKED_SOLO_5x5, Tier::CHALLENGER, Division::I, None); - let d = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get challenger exp league entries.".to_owned())?; + let d = p.await.map_err(|e| e.to_string())?; rassert!(!d.is_empty(), "Challenger shouldn't be empty."); Ok(()) }, match_get: async { let p = RIOT_API.match_v4().get_match(Region::NA, 3190191338); - let m = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get match.".to_owned())?; + let m = p.await.map_err(|e| e.to_string())?.ok_or("Match not found.".to_owned())?; rassert!(!m.participants.is_empty(), "Match should have participants."); Ok(()) }, diff --git a/tests/tests_tr.rs b/tests/tests_tr.rs index b2e7dc0..ca6c26b 100644 --- a/tests/tests_tr.rs +++ b/tests/tests_tr.rs @@ -18,7 +18,7 @@ async_tests!{ league_summoner_bulk_test: async { let p = RIOT_API.league_v4().get_challenger_league(REGION, QueueType::RANKED_SOLO_5x5); // let p = future_start(p); - let ll = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get challenger league".to_owned())?; + let ll = p.await.map_err(|e| e.to_string())?; println!("{:?} Challenger {} entries.", REGION, ll.entries.len()); @@ -28,8 +28,7 @@ async_tests!{ .collect::>(); for (i, s) in sl.into_iter().enumerate() { - let summoner_opt: Option = s.await.map_err(|e| e.to_string())?; - let summoner = summoner_opt.ok_or("Failed to get summoner.".to_owned())?; + let summoner: Summoner = s.await.map_err(|e| e.to_string())?; println!("{}: {}", i + 1, summoner.name); }