mirror of
https://github.com/MingweiSamuel/Riven.git
synced 2024-12-25 18:36:31 +00:00
Big generic client compiling
This commit is contained in:
parent
5d2925c0fa
commit
41ef6d9c2e
8 changed files with 172 additions and 173 deletions
|
@ -1,3 +1,4 @@
|
|||
use std::fmt::Debug;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
|
@ -5,20 +6,21 @@ use serde::de::DeserializeOwned;
|
|||
|
||||
pub type BoxFut<T> = Pin<Box<dyn Future<Output = T> + Send>>;
|
||||
|
||||
pub trait Client<R, E, E2> where
|
||||
R: Response<E2>,
|
||||
{
|
||||
pub trait Client {
|
||||
type Resp: Response;
|
||||
type Err: Debug;
|
||||
fn new() -> Self;
|
||||
fn get(&self, url_base: String, url_path: String, url_query: Option<String>,
|
||||
headers: Vec<(&'static str, String)>) -> BoxFut<Result<R, E>>;
|
||||
fn get(&self, url_base: String, url_path: &str, url_query: Option<&str>,
|
||||
headers: Vec<(&'static str, &str)>) -> BoxFut<Result<Self::Resp, <Self::Resp as Response>::Err>>;
|
||||
}
|
||||
|
||||
// TODO: custom/generic HeaderValue trait? And for keys?
|
||||
pub trait Response<E> {
|
||||
fn status_code(&self) -> u16;
|
||||
pub trait Response {
|
||||
type Err: Debug;
|
||||
fn status(&self) -> u16;
|
||||
fn verison(&self) -> String;
|
||||
fn header(&self, key: String) -> Option<String>;
|
||||
fn headers_all(&self, key: String) -> Vec<String>;
|
||||
fn into_body(self) -> BoxFut<Result<String, E>>;
|
||||
fn into_json<T: DeserializeOwned + 'static>(self) -> BoxFut<Result<T, E>>;
|
||||
fn header(&self, key: &str) -> Option<String>;
|
||||
fn headers_all(&self, key: &str) -> Vec<String>;
|
||||
fn into_body(self) -> BoxFut<Result<String, Self::Err>>;
|
||||
fn into_json<T: DeserializeOwned + 'static>(self) -> BoxFut<Result<T, Self::Err>>;
|
||||
}
|
||||
|
|
|
@ -5,26 +5,24 @@ use serde::de::DeserializeOwned;
|
|||
|
||||
use super::{ Client, Response, BoxFut };
|
||||
|
||||
impl Client<reqwest::Response, reqwest::Error, reqwest::Error> for reqwest::Client {
|
||||
impl Client for reqwest::Client {
|
||||
type Resp = reqwest::Response;
|
||||
type Err = reqwest::Error;
|
||||
fn new() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
fn get(&self, url_base: String, url_path: String, url_query: Option<String>,
|
||||
headers: Vec<(&'static str, String)>) -> BoxFut<Result<reqwest::Response, reqwest::Error>>
|
||||
fn get(&self, url_base: String, url_path: &str, url_query: Option<&str>,
|
||||
headers: Vec<(&'static str, &str)>) -> BoxFut<Result<reqwest::Response, reqwest::Error>>
|
||||
{
|
||||
#[cfg(feature = "nightly")] let url_query = url_query.as_deref();
|
||||
#[cfg(not(feature = "nightly"))] let url_query = url_query.as_ref().map(|s| s.as_ref());
|
||||
|
||||
let mut url = reqwest::Url::parse(&*url_base)
|
||||
.unwrap_or_else(|_| panic!("Failed to parse url_base: \"{}\".", url_base));
|
||||
url.set_path(&*url_path);
|
||||
url.set_path(url_path);
|
||||
url.set_query(url_query);
|
||||
|
||||
let header_iter = headers.into_iter()
|
||||
.map(|(key, value)| (
|
||||
key.try_into().unwrap_or_else(|_| panic!("Invalid header key: \"{}\".", &key)),
|
||||
// Makes a copy.
|
||||
(&value).try_into().unwrap_or_else(|_| panic!("Invalid header value: \"{}\".", &value)),
|
||||
key.try_into().unwrap_or_else(|_| panic!("Invalid header key: \"{}\".", key)),
|
||||
value.try_into().unwrap_or_else(|_| panic!("Invalid header value: \"{}\".", value)),
|
||||
));
|
||||
let header_map = reqwest::header::HeaderMap::from_iter(header_iter);
|
||||
|
||||
|
@ -35,19 +33,20 @@ impl Client<reqwest::Response, reqwest::Error, reqwest::Error> for reqwest::Clie
|
|||
}
|
||||
}
|
||||
|
||||
impl Response<reqwest::Error> for reqwest::Response {
|
||||
fn status_code(&self) -> u16 {
|
||||
impl Response for reqwest::Response {
|
||||
type Err = reqwest::Error;
|
||||
fn status(&self) -> u16 {
|
||||
self.status().as_u16()
|
||||
}
|
||||
fn verison(&self) -> String {
|
||||
format!("{:?}", self.version())
|
||||
}
|
||||
fn header(&self, key: String) -> Option<String> {
|
||||
fn header(&self, key: &str) -> Option<String> {
|
||||
self.headers().get(key)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.map(|value| value.to_owned())
|
||||
}
|
||||
fn headers_all(&self, key: String) -> Vec<String> {
|
||||
fn headers_all(&self, key: &str) -> Vec<String> {
|
||||
self.headers().get_all(key).iter()
|
||||
.filter_map(|value| value.to_str().ok())
|
||||
.map(|value| value.to_owned())
|
||||
|
|
135
src/endpoints.rs
135
src/endpoints.rs
|
@ -7,7 +7,7 @@
|
|||
///////////////////////////////////////////////
|
||||
|
||||
// http://www.mingweisamuel.com/riotapi-schema/tool/
|
||||
// Version 71bb788ab92c0b03d5dd284402d9514b625fe2a4
|
||||
// Version 64f3c82d132f12808d8eb8f483d1d2182386c432
|
||||
|
||||
//! Automatically generated endpoint handles.
|
||||
|
||||
|
@ -19,17 +19,18 @@ use std::vec::Vec;
|
|||
use url::form_urlencoded::Serializer;
|
||||
|
||||
use crate::Result;
|
||||
use crate::client::Client;
|
||||
use crate::consts::Region;
|
||||
use crate::riot_api::RiotApi;
|
||||
|
||||
impl RiotApi {
|
||||
impl<C: Client> RiotApi<C> {
|
||||
/// Returns a handle for accessing [ChampionMasteryV4](crate::endpoints::ChampionMasteryV4) endpoints.
|
||||
/// # Riot Developer API Reference
|
||||
/// <a href="https://developer.riotgames.com/apis#champion-mastery-v4" target="_blank">`champion-mastery-v4`</a>
|
||||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn champion_mastery_v4(&self) -> ChampionMasteryV4 {
|
||||
pub fn champion_mastery_v4(&self) -> ChampionMasteryV4<C> {
|
||||
ChampionMasteryV4 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [ChampionV3](crate::endpoints::ChampionV3) endpoints.
|
||||
|
@ -38,7 +39,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn champion_v3(&self) -> ChampionV3 {
|
||||
pub fn champion_v3(&self) -> ChampionV3<C> {
|
||||
ChampionV3 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [ClashV1](crate::endpoints::ClashV1) endpoints.
|
||||
|
@ -47,7 +48,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn clash_v1(&self) -> ClashV1 {
|
||||
pub fn clash_v1(&self) -> ClashV1<C> {
|
||||
ClashV1 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [LeagueExpV4](crate::endpoints::LeagueExpV4) endpoints.
|
||||
|
@ -56,7 +57,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn league_exp_v4(&self) -> LeagueExpV4 {
|
||||
pub fn league_exp_v4(&self) -> LeagueExpV4<C> {
|
||||
LeagueExpV4 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [LeagueV4](crate::endpoints::LeagueV4) endpoints.
|
||||
|
@ -65,7 +66,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn league_v4(&self) -> LeagueV4 {
|
||||
pub fn league_v4(&self) -> LeagueV4<C> {
|
||||
LeagueV4 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [LolStatusV3](crate::endpoints::LolStatusV3) endpoints.
|
||||
|
@ -74,7 +75,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn lol_status_v3(&self) -> LolStatusV3 {
|
||||
pub fn lol_status_v3(&self) -> LolStatusV3<C> {
|
||||
LolStatusV3 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [LorRankedV1](crate::endpoints::LorRankedV1) endpoints.
|
||||
|
@ -83,7 +84,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn lor_ranked_v1(&self) -> LorRankedV1 {
|
||||
pub fn lor_ranked_v1(&self) -> LorRankedV1<C> {
|
||||
LorRankedV1 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [MatchV4](crate::endpoints::MatchV4) endpoints.
|
||||
|
@ -92,7 +93,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn match_v4(&self) -> MatchV4 {
|
||||
pub fn match_v4(&self) -> MatchV4<C> {
|
||||
MatchV4 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [SpectatorV4](crate::endpoints::SpectatorV4) endpoints.
|
||||
|
@ -101,7 +102,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn spectator_v4(&self) -> SpectatorV4 {
|
||||
pub fn spectator_v4(&self) -> SpectatorV4<C> {
|
||||
SpectatorV4 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [SummonerV4](crate::endpoints::SummonerV4) endpoints.
|
||||
|
@ -110,7 +111,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn summoner_v4(&self) -> SummonerV4 {
|
||||
pub fn summoner_v4(&self) -> SummonerV4<C> {
|
||||
SummonerV4 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [TftLeagueV1](crate::endpoints::TftLeagueV1) endpoints.
|
||||
|
@ -119,7 +120,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn tft_league_v1(&self) -> TftLeagueV1 {
|
||||
pub fn tft_league_v1(&self) -> TftLeagueV1<C> {
|
||||
TftLeagueV1 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [TftMatchV1](crate::endpoints::TftMatchV1) endpoints.
|
||||
|
@ -128,7 +129,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn tft_match_v1(&self) -> TftMatchV1 {
|
||||
pub fn tft_match_v1(&self) -> TftMatchV1<C> {
|
||||
TftMatchV1 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [TftSummonerV1](crate::endpoints::TftSummonerV1) endpoints.
|
||||
|
@ -137,7 +138,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn tft_summoner_v1(&self) -> TftSummonerV1 {
|
||||
pub fn tft_summoner_v1(&self) -> TftSummonerV1<C> {
|
||||
TftSummonerV1 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [ThirdPartyCodeV4](crate::endpoints::ThirdPartyCodeV4) endpoints.
|
||||
|
@ -146,7 +147,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn third_party_code_v4(&self) -> ThirdPartyCodeV4 {
|
||||
pub fn third_party_code_v4(&self) -> ThirdPartyCodeV4<C> {
|
||||
ThirdPartyCodeV4 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [TournamentStubV4](crate::endpoints::TournamentStubV4) endpoints.
|
||||
|
@ -155,7 +156,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn tournament_stub_v4(&self) -> TournamentStubV4 {
|
||||
pub fn tournament_stub_v4(&self) -> TournamentStubV4<C> {
|
||||
TournamentStubV4 { base: self }
|
||||
}
|
||||
/// Returns a handle for accessing [TournamentV4](crate::endpoints::TournamentV4) endpoints.
|
||||
|
@ -164,7 +165,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn tournament_v4(&self) -> TournamentV4 {
|
||||
pub fn tournament_v4(&self) -> TournamentV4<C> {
|
||||
TournamentV4 { base: self }
|
||||
}
|
||||
}
|
||||
|
@ -174,10 +175,10 @@ impl RiotApi {
|
|||
/// <a href="https://developer.riotgames.com/apis#champion-mastery-v4" target="_blank">`champion-mastery-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct ChampionMasteryV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct ChampionMasteryV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> ChampionMasteryV4<'a> {
|
||||
impl<'a, C: Client> ChampionMasteryV4<'a, C> {
|
||||
/// Get all champion mastery entries sorted by number of champion points descending,
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -231,10 +232,10 @@ impl<'a> ChampionMasteryV4<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#champion-v3" target="_blank">`champion-v3`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct ChampionV3<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct ChampionV3<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> ChampionV3<'a> {
|
||||
impl<'a, C: Client> ChampionV3<'a, C> {
|
||||
/// Returns champion rotations, including free-to-play and low-level free-to-play rotations (REST)
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -256,11 +257,13 @@ impl<'a> ChampionV3<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#clash-v1" target="_blank">`clash-v1`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct ClashV1<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct ClashV1<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> ClashV1<'a> {
|
||||
impl<'a, C: Client> ClashV1<'a, C> {
|
||||
/// Get players by summoner ID.
|
||||
/// ## Implementation Notes
|
||||
/// This endpoint returns a list of active Clash players for a given summoner ID. If a summoner registers for multiple tournaments at the same time (e.g., Saturday and Sunday) then both registrations would appear in this list.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
/// * `summonerId`
|
||||
|
@ -341,10 +344,10 @@ impl<'a> ClashV1<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#league-exp-v4" target="_blank">`league-exp-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct LeagueExpV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct LeagueExpV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> LeagueExpV4<'a> {
|
||||
impl<'a, C: Client> LeagueExpV4<'a, C> {
|
||||
/// Get all the league entries.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -373,10 +376,10 @@ impl<'a> LeagueExpV4<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#league-v4" target="_blank">`league-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct LeagueV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct LeagueV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> LeagueV4<'a> {
|
||||
impl<'a, C: Client> LeagueV4<'a, C> {
|
||||
/// Get the challenger league for given queue.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -480,10 +483,10 @@ impl<'a> LeagueV4<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#lol-status-v3" target="_blank">`lol-status-v3`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct LolStatusV3<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct LolStatusV3<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> LolStatusV3<'a> {
|
||||
impl<'a, C: Client> LolStatusV3<'a, C> {
|
||||
/// Get League of Legends status for the given shard.
|
||||
/// ## Rate Limit Notes
|
||||
/// Requests to this API are not counted against the application Rate Limits.
|
||||
|
@ -507,10 +510,10 @@ impl<'a> LolStatusV3<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#lor-ranked-v1" target="_blank">`lor-ranked-v1`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct LorRankedV1<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct LorRankedV1<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> LorRankedV1<'a> {
|
||||
impl<'a, C: Client> LorRankedV1<'a, C> {
|
||||
/// Get the players in Master tier.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -532,10 +535,10 @@ impl<'a> LorRankedV1<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#match-v4" target="_blank">`match-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct MatchV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct MatchV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> MatchV4<'a> {
|
||||
impl<'a, C: Client> MatchV4<'a, C> {
|
||||
/// Get match IDs by tournament code.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -643,10 +646,10 @@ impl<'a> MatchV4<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#spectator-v4" target="_blank">`spectator-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct SpectatorV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct SpectatorV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> SpectatorV4<'a> {
|
||||
impl<'a, C: Client> SpectatorV4<'a, C> {
|
||||
/// Get current game information for the given summoner ID.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -683,10 +686,10 @@ impl<'a> SpectatorV4<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#summoner-v4" target="_blank">`summoner-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct SummonerV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct SummonerV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> SummonerV4<'a> {
|
||||
impl<'a, C: Client> SummonerV4<'a, C> {
|
||||
/// Get a summoner by account ID.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -754,10 +757,10 @@ impl<'a> SummonerV4<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#tft-league-v1" target="_blank">`tft-league-v1`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct TftLeagueV1<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct TftLeagueV1<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> TftLeagueV1<'a> {
|
||||
impl<'a, C: Client> TftLeagueV1<'a, C> {
|
||||
/// Get the challenger league.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -857,10 +860,10 @@ impl<'a> TftLeagueV1<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#tft-match-v1" target="_blank">`tft-match-v1`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct TftMatchV1<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct TftMatchV1<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> TftMatchV1<'a> {
|
||||
impl<'a, C: Client> TftMatchV1<'a, C> {
|
||||
/// Get a list of match ids by PUUID.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -902,10 +905,10 @@ impl<'a> TftMatchV1<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#tft-summoner-v1" target="_blank">`tft-summoner-v1`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct TftSummonerV1<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct TftSummonerV1<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> TftSummonerV1<'a> {
|
||||
impl<'a, C: Client> TftSummonerV1<'a, C> {
|
||||
/// Get a summoner by account ID.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -973,10 +976,10 @@ impl<'a> TftSummonerV1<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#third-party-code-v4" target="_blank">`third-party-code-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct ThirdPartyCodeV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct ThirdPartyCodeV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> ThirdPartyCodeV4<'a> {
|
||||
impl<'a, C: Client> ThirdPartyCodeV4<'a, C> {
|
||||
/// Get third party code for a given summoner ID.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -999,10 +1002,10 @@ impl<'a> ThirdPartyCodeV4<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#tournament-stub-v4" target="_blank">`tournament-stub-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct TournamentStubV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct TournamentStubV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> TournamentStubV4<'a> {
|
||||
impl<'a, C: Client> TournamentStubV4<'a, C> {
|
||||
/// Gets a mock list of lobby events by tournament code.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
@ -1025,10 +1028,10 @@ impl<'a> TournamentStubV4<'a> {
|
|||
/// <a href="https://developer.riotgames.com/apis#tournament-v4" target="_blank">`tournament-v4`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct TournamentV4<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct TournamentV4<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> TournamentV4<'a> {
|
||||
impl<'a, C: Client> TournamentV4<'a, C> {
|
||||
/// Returns the tournament code DTO associated with a tournament code string.
|
||||
/// # Parameters
|
||||
/// * `region` - Region to query.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
///////////////////////////////////////////////
|
||||
|
||||
// http://www.mingweisamuel.com/riotapi-schema/tool/
|
||||
// Version 71bb788ab92c0b03d5dd284402d9514b625fe2a4
|
||||
// Version 64f3c82d132f12808d8eb8f483d1d2182386c432
|
||||
|
||||
//! Data transfer structs.
|
||||
//!
|
||||
|
@ -466,7 +466,7 @@ pub mod match_v4 {
|
|||
pub struct ParticipantIdentity {
|
||||
#[serde(rename = "participantId")]
|
||||
pub participant_id: i32,
|
||||
/// Player information.
|
||||
/// Player information not included in the response for custom matches. Custom matches are considered private unless a tournament code was used to create the match.
|
||||
#[serde(rename = "player")]
|
||||
pub player: Player,
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ use std::time::{ Duration, Instant };
|
|||
|
||||
use log;
|
||||
use parking_lot::{ RwLock, RwLockUpgradableReadGuard };
|
||||
use reqwest::{ StatusCode, Response };
|
||||
use scan_fmt::scan_fmt;
|
||||
|
||||
use crate::RiotApiConfig;
|
||||
use crate::client::Response;
|
||||
use super::{ TokenBucket, VectorTokenBucket };
|
||||
use super::RateLimitType;
|
||||
|
||||
|
@ -68,25 +68,25 @@ impl RateLimit {
|
|||
self.retry_after.read().and_then(|i| Instant::now().checked_duration_since(i))
|
||||
}
|
||||
|
||||
pub fn on_response(&self, config: &RiotApiConfig, response: &Response) {
|
||||
pub fn on_response<R: Response>(&self, config: &RiotApiConfig, response: &R) {
|
||||
self.on_response_retry_after(response);
|
||||
self.on_response_rate_limits(config, response);
|
||||
}
|
||||
|
||||
/// `on_response` helper for retry after check.
|
||||
#[inline]
|
||||
fn on_response_retry_after(&self, response: &Response) {
|
||||
fn on_response_retry_after<R: Response>(&self, response: &R) {
|
||||
if let Some(retry_after) = || -> Option<Instant> {
|
||||
// Only care about 429s.
|
||||
if StatusCode::TOO_MANY_REQUESTS != response.status() {
|
||||
// Only care about 429 Too Many Requests.
|
||||
if 429 != response.status() {
|
||||
return None;
|
||||
}
|
||||
|
||||
{
|
||||
// Only care if the header that indicates the relevant RateLimit is present.
|
||||
let type_name_header = response.headers()
|
||||
.get(RateLimit::HEADER_XRATELIMITTYPE)?.to_str()
|
||||
.expect("Failed to read x-rate-limit-type header as string.");
|
||||
let type_name_header = response
|
||||
.header(RateLimit::HEADER_XRATELIMITTYPE)?;
|
||||
// .expect("Failed to read x-rate-limit-type header as string.");
|
||||
// Only care if that header's value matches us.
|
||||
if self.rate_limit_type.type_name() != type_name_header.to_lowercase() {
|
||||
return None;
|
||||
|
@ -94,9 +94,9 @@ impl RateLimit {
|
|||
}
|
||||
|
||||
// Get retry after header. Only care if it exists.
|
||||
let retry_after_header = response.headers()
|
||||
.get(RateLimit::HEADER_RETRYAFTER)?.to_str()
|
||||
.expect("Failed to read retry-after header as string.");
|
||||
let retry_after_header = response
|
||||
.header(RateLimit::HEADER_RETRYAFTER)?;
|
||||
// .expect("Failed to read retry-after header as string.");
|
||||
|
||||
log::debug!("Hit 429, retry-after {} secs.", retry_after_header);
|
||||
|
||||
|
@ -112,26 +112,26 @@ impl RateLimit {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn on_response_rate_limits(&self, config: &RiotApiConfig, response: &Response) {
|
||||
fn on_response_rate_limits<R: Response>(&self, config: &RiotApiConfig, response: &R) {
|
||||
// Check if rate limits changed.
|
||||
let headers = response.headers();
|
||||
let limit_header_opt = headers.get(self.rate_limit_type.limit_header())
|
||||
.map(|h| h.to_str().expect("Failed to read limit header as string."));
|
||||
let count_header_opt = headers.get(self.rate_limit_type.count_header())
|
||||
.map(|h| h.to_str().expect("Failed to read count header as string."));
|
||||
// let headers = response.headers();
|
||||
let limit_header_opt = response.header(self.rate_limit_type.limit_header());
|
||||
// .map(|h| h.to_str().expect("Failed to read limit header as string."));
|
||||
let count_header_opt = response.header(self.rate_limit_type.count_header());
|
||||
// .map(|h| h.to_str().expect("Failed to read count header as string."));
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/53667
|
||||
if let Some(limit_header) = limit_header_opt {
|
||||
if let Some(count_header) = count_header_opt {
|
||||
|
||||
let buckets = self.buckets.upgradable_read();
|
||||
if !buckets_require_updating(limit_header, &*buckets) {
|
||||
if !buckets_require_updating(&limit_header, &*buckets) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Buckets require updating. Upgrade to write lock.
|
||||
let mut buckets = RwLockUpgradableReadGuard::upgrade(buckets);
|
||||
*buckets = buckets_from_header(config, limit_header, count_header)
|
||||
*buckets = buckets_from_header(config, &limit_header, &count_header)
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ use std::future::Future;
|
|||
use std::sync::Arc;
|
||||
|
||||
use log;
|
||||
use reqwest::{ Client, StatusCode, Url };
|
||||
use tokio::time::delay_for;
|
||||
|
||||
use crate::client::{ Client, Response };
|
||||
use crate::Result;
|
||||
use crate::RiotApiError;
|
||||
use crate::RiotApiConfig;
|
||||
|
@ -25,9 +25,9 @@ impl RegionalRequester {
|
|||
const RIOT_KEY_HEADER: &'static str = "X-Riot-Token";
|
||||
|
||||
/// HTTP status codes which are considered a success but will results in `None`.
|
||||
const NONE_STATUS_CODES: [StatusCode; 2] = [
|
||||
StatusCode::NO_CONTENT, // 204
|
||||
StatusCode::NOT_FOUND, // 404
|
||||
const NONE_STATUS_CODES: [u16; 2] = [
|
||||
204, // No Content.
|
||||
404, // Not Found.
|
||||
];
|
||||
|
||||
pub fn new() -> Self {
|
||||
|
@ -37,27 +37,28 @@ impl RegionalRequester {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_optional<'a, T: serde::de::DeserializeOwned>(self: Arc<Self>,
|
||||
config: &'a RiotApiConfig, client: &'a Client,
|
||||
pub fn get_optional<'a, C: Client, T: serde::de::DeserializeOwned + 'static>(self: Arc<Self>,
|
||||
config: &'a RiotApiConfig, client: &'a C,
|
||||
method_id: &'static str, region_platform: &'a str, path: String, query: Option<String>)
|
||||
-> impl Future<Output = Result<Option<T>>> + '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(status) = e.status_code() {
|
||||
if Self::NONE_STATUS_CODES.contains(&status) {
|
||||
return Ok(None);
|
||||
}}
|
||||
Err(e)
|
||||
})
|
||||
panic!("FIXME");
|
||||
// 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(status) = e.status_code() {
|
||||
// if Self::NONE_STATUS_CODES.contains(&status) {
|
||||
// return Ok(None);
|
||||
// }}
|
||||
// Err(e)
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<'a, T: serde::de::DeserializeOwned>(self: Arc<Self>,
|
||||
config: &'a RiotApiConfig, client: &'a Client,
|
||||
pub fn get<'a, C: Client, T: serde::de::DeserializeOwned + 'static>(self: Arc<Self>,
|
||||
config: &'a RiotApiConfig, client: &'a C,
|
||||
method_id: &'static str, region_platform: &'a str, path: String, query: Option<String>)
|
||||
-> impl Future<Output = Result<T>> + 'a
|
||||
{
|
||||
|
@ -77,16 +78,10 @@ impl RegionalRequester {
|
|||
|
||||
// Send request.
|
||||
let url_base = format!("https://{}.api.riotgames.com", region_platform);
|
||||
let mut url = Url::parse(&*url_base)
|
||||
.unwrap_or_else(|_| panic!("Failed to parse url_base: \"{}\".", url_base));
|
||||
url.set_path(&*path);
|
||||
url.set_query(query);
|
||||
|
||||
let response = client.get(url)
|
||||
.header(Self::RIOT_KEY_HEADER, &*config.api_key)
|
||||
.send()
|
||||
let response = client.get(url_base, &path, query, vec![( Self::RIOT_KEY_HEADER, &config.api_key )])
|
||||
.await
|
||||
.map_err(|e| RiotApiError::new(e, retries, None, None))?;
|
||||
.unwrap(); // FIXME
|
||||
// .map_err(|e| RiotApiError::new(e, retries, None, None))?;
|
||||
|
||||
// Maybe update rate limits (based on response headers).
|
||||
self.app_rate_limit.on_response(&config, &response);
|
||||
|
@ -94,27 +89,20 @@ impl RegionalRequester {
|
|||
|
||||
let status = response.status();
|
||||
// Handle normal success / failure cases.
|
||||
match response.error_for_status_ref() {
|
||||
if 200 == status {
|
||||
// Success.
|
||||
Ok(_response) => {
|
||||
log::trace!("Response {} (retried {} times), parsed result.", status, retries);
|
||||
let value = response.json::<T>().await;
|
||||
break value.map_err(|e| RiotApiError::new(e, retries, None, Some(status)));
|
||||
},
|
||||
// Failure, may or may not be retryable.
|
||||
Err(err) => {
|
||||
// Not-retryable: no more retries or 4xx or ? (3xx, redirects exceeded).
|
||||
// Retryable: retries remaining, and 429 or 5xx.
|
||||
if retries >= config.retries ||
|
||||
(StatusCode::TOO_MANY_REQUESTS != status
|
||||
&& !status.is_server_error())
|
||||
{
|
||||
log::debug!("Response {} (retried {} times), returning.", status, retries);
|
||||
break Err(RiotApiError::new(err, retries, Some(response), Some(status)));
|
||||
}
|
||||
log::debug!("Response {} (retried {} times), retrying.", status, retries);
|
||||
},
|
||||
};
|
||||
log::trace!("Response {} (retried {} times), parsed result.", status, retries);
|
||||
let value = response.into_json::<T>().await;
|
||||
break value.map_err(|e| panic!("FIXME")); //RiotApiError::new(Some(e), retries, None, Some(status)));
|
||||
}
|
||||
// Not-retryable: no more retries or 4xx or ? (3xx, redirects exceeded).
|
||||
// Retryable: retries remaining, and 429 or 5xx.
|
||||
if retries >= config.retries || (429 != status && 500 > status)
|
||||
{
|
||||
log::debug!("Response {} (retried {} times), returning.", status, retries);
|
||||
panic!("FIXME"); // FIXME break Err(RiotApiError::new(None, retries, Some(response), Some(status)));
|
||||
}
|
||||
log::debug!("Response {} (retried {} times), retrying.", status, retries);
|
||||
|
||||
retries += 1;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ use std::future::Future;
|
|||
use std::sync::Arc;
|
||||
|
||||
use log;
|
||||
use reqwest::Client;
|
||||
|
||||
use crate::Result;
|
||||
use crate::client::Client;
|
||||
use crate::RiotApiConfig;
|
||||
use crate::req::RegionalRequester;
|
||||
use crate::util::InsertOnlyCHashMap;
|
||||
|
@ -34,24 +34,30 @@ use crate::util::InsertOnlyCHashMap;
|
|||
///
|
||||
/// To adjust rate limiting, see [RiotApiConfig](crate::RiotApiConfig) and use
|
||||
/// [`with_config(config)`](RiotApi::with_config) to construct an instance.
|
||||
pub struct RiotApi {
|
||||
pub struct RiotApi<C: Client> {
|
||||
/// Configuration settings.
|
||||
config: RiotApiConfig,
|
||||
/// Client for making requests.
|
||||
client: Client,
|
||||
client: C,
|
||||
|
||||
/// Per-region requesters.
|
||||
regional_requesters: InsertOnlyCHashMap<&'static str, RegionalRequester>,
|
||||
}
|
||||
|
||||
impl RiotApi {
|
||||
impl<C: Client> RiotApi<C> {
|
||||
/// Constructs a new instance from the given [RiotApiConfig](crate::RiotApiConfig), consuming it.
|
||||
pub fn with_config(mut config: RiotApiConfig) -> Self {
|
||||
let client_builder = config.client_builder.take()
|
||||
.expect("!NONE CLIENT_BUILDER IN CONFIG.");
|
||||
//FIXME
|
||||
// let client_builder = config.client_builder.take()
|
||||
// .expect("!NONE CLIENT_BUILDER IN CONFIG.");
|
||||
// Self {
|
||||
// config: config,
|
||||
// client: client_builder.build().expect("Failed to create client from builder."),
|
||||
// regional_requesters: InsertOnlyCHashMap::new(),
|
||||
// }
|
||||
Self {
|
||||
config: config,
|
||||
client: client_builder.build().expect("Failed to create client from builder."),
|
||||
client: C::new(),
|
||||
regional_requesters: InsertOnlyCHashMap::new(),
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +80,7 @@ impl RiotApi {
|
|||
/// * `region_platform` - The stringified platform, prepended to `.api.riotgames.com` to create the hostname.
|
||||
/// * `path` - The path relative to the hostname.
|
||||
/// * `query` - An optional query string.
|
||||
pub fn get_optional<'a, T: serde::de::DeserializeOwned + 'a>(&'a self,
|
||||
pub fn get_optional<'a, T: serde::de::DeserializeOwned + 'static>(&'a self,
|
||||
method_id: &'static str, region_platform: &'static str, path: String, query: Option<String>)
|
||||
-> impl Future<Output = Result<Option<T>>> + 'a
|
||||
{
|
||||
|
@ -91,7 +97,7 @@ impl RiotApi {
|
|||
/// * `region_platform` - The stringified platform, prepended to `.api.riotgames.com` to create the hostname.
|
||||
/// * `path` - The path relative to the hostname.
|
||||
/// * `query` - An optional query string.
|
||||
pub fn get<'a, T: serde::de::DeserializeOwned + 'a>(&'a self,
|
||||
pub fn get<'a, T: serde::de::DeserializeOwned + 'static>(&'a self,
|
||||
method_id: &'static str, region_platform: &'static str, path: String, query: Option<String>)
|
||||
-> impl Future<Output = Result<T>> + 'a
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ use std::vec::Vec;
|
|||
use url::form_urlencoded::Serializer;
|
||||
|
||||
use crate::Result;
|
||||
use crate::client::Client;
|
||||
use crate::consts::Region;
|
||||
use crate::riot_api::RiotApi;
|
||||
|
||||
|
@ -27,7 +28,7 @@ use crate::riot_api::RiotApi;
|
|||
endpointGroups[ep].push(path);
|
||||
}
|
||||
}}
|
||||
impl RiotApi {
|
||||
impl<C: Client> RiotApi<C> {
|
||||
{{
|
||||
for (const endpointName of Object.keys(endpointGroups)) {
|
||||
const method = dotUtils.changeCase.snakeCase(endpointName);
|
||||
|
@ -39,7 +40,7 @@ impl RiotApi {
|
|||
///
|
||||
/// Note: this method is automatically generated.
|
||||
#[inline]
|
||||
pub fn {{= method }}(&self) -> {{= type }} {
|
||||
pub fn {{= method }}(&self) -> {{= type }}<C> {
|
||||
{{= type }} { base: self }
|
||||
}
|
||||
{{
|
||||
|
@ -57,10 +58,10 @@ impl RiotApi {
|
|||
/// <a href="https://developer.riotgames.com/apis#{{= endpointName }}" target="_blank">`{{= endpointName }}`</a>
|
||||
///
|
||||
/// Note: this struct is automatically generated.
|
||||
pub struct {{= endpoint }}<'a> {
|
||||
base: &'a RiotApi,
|
||||
pub struct {{= endpoint }}<'a, C: Client> {
|
||||
base: &'a RiotApi<C>,
|
||||
}
|
||||
impl<'a> {{= endpoint }}<'a> {
|
||||
impl<'a, C: Client> {{= endpoint }}<'a, C> {
|
||||
{{
|
||||
for (let [ route, path ] of endpointMethods)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue