diff --git a/RiotSharp.AspNetCore/IServiceCollectionExtension.cs b/RiotSharp.AspNetCore/IServiceCollectionExtension.cs index 2991eb78..01e3883c 100644 --- a/RiotSharp.AspNetCore/IServiceCollectionExtension.cs +++ b/RiotSharp.AspNetCore/IServiceCollectionExtension.cs @@ -3,6 +3,8 @@ using RiotSharp.Interfaces; using System; using System.Collections.Generic; +using System.Net.Http; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace RiotSharp.AspNetCore { @@ -25,18 +27,27 @@ public static IServiceCollection AddRiotSharp(this IServiceCollection serviceCol if (riotSharpOptions.TournamentApi.ApiKey == null && riotSharpOptions.RiotApi.ApiKey == null) throw new ArgumentNullException("No api key provided.", innerException: null); + var serializer = new RequestContentSerializer(); + var deserializer = new ResponseDeserializer(); + var httpClient = new HttpClient(); + var failedRequestHandler = new FailedRequestHandler(); + var client = new RequestClient(httpClient, failedRequestHandler); + if (riotSharpOptions.RiotApi.ApiKey != null) { - var rateLimitedRequester = new RateLimitedRequester(riotSharpOptions.RiotApi.ApiKey, - riotSharpOptions.RiotApi.RateLimits); - serviceCollection.AddSingleton(serviceProvider => - new TournamentRiotApi(rateLimitedRequester)); - serviceCollection.AddSingleton(serviceProvider => new RiotApi(rateLimitedRequester)); + var requestCreator = new RequestCreator(riotSharpOptions.RiotApi.ApiKey, serializer); + var basicRequester = new Requester(client, requestCreator, deserializer); + var riotRateLimitProvider = new RateLimitProvider(riotSharpOptions.RiotApi.RateLimits); + + + var riotRateLimitedRequester = new RateLimitedRequester(basicRequester, riotRateLimitProvider); + + serviceCollection.AddSingleton(provider => new RiotApi(riotRateLimitedRequester)); - var staticApiRequester = new RateLimitedRequester(riotSharpOptions.RiotApi.ApiKey, new Dictionary - { - { new TimeSpan(1, 0, 0), 10 } - }); + + var staticRateLimitProvider = new RateLimitProvider(new Dictionary{{new TimeSpan(1, 0, 0), 10}}); + + var staticRateLimtedRequester = new RateLimitedRequester(basicRequester, staticRateLimitProvider); if (riotSharpOptions.RiotApi.UseMemoryCache) { @@ -49,15 +60,19 @@ public static IServiceCollection AddRiotSharp(this IServiceCollection serviceCol serviceCollection.AddSingleton(); serviceCollection.AddSingleton(serviceProvider => - new StaticRiotApi(staticApiRequester, serviceProvider.GetRequiredService(), riotSharpOptions.RiotApi.SlidingExpirationTime)); + new StaticRiotApi(staticRateLimtedRequester, serviceProvider.GetRequiredService(), riotSharpOptions.RiotApi.SlidingExpirationTime)); } if (riotSharpOptions.TournamentApi.ApiKey != null) { - var rateLimitedRequester = new RateLimitedRequester(riotSharpOptions.TournamentApi.ApiKey, - riotSharpOptions.TournamentApi.RateLimits); - serviceCollection.AddSingleton(serviceProvider => - new TournamentRiotApi(rateLimitedRequester, riotSharpOptions.TournamentApi.UseStub)); + var requestCreator = new RequestCreator(riotSharpOptions.TournamentApi.ApiKey, serializer); + var basicRequester = new Requester(client, requestCreator, deserializer); + var riotRateLimitProvider = new RateLimitProvider(riotSharpOptions.TournamentApi.RateLimits); + + + var tournamentRateLimitedRequester = new RateLimitedRequester(basicRequester, riotRateLimitProvider); + + serviceCollection.AddSingleton(serviceProvider => new TournamentRiotApi(tournamentRateLimitedRequester, riotSharpOptions.TournamentApi.UseStub)); } return serviceCollection; diff --git a/RiotSharp.Test/RateLimitedRequesterTestDoubles.cs b/RiotSharp.Test/RateLimitedRequesterTestDoubles.cs new file mode 100644 index 00000000..541ca142 --- /dev/null +++ b/RiotSharp.Test/RateLimitedRequesterTestDoubles.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using RiotSharp.Http; +using RiotSharp.Http.Interfaces; + +namespace RiotSharp.Test +{ + class RateLimitedRequesterTestDoubles + { + public static IRateLimitedRequester Real(string apiKey, IDictionary rateLimits) + { + var serializer = new RequestContentSerializer(); + var deserializer = new ResponseDeserializer(); + var requestCreator = new RequestCreator(apiKey, serializer); + var httpClient = new HttpClient(); + var failedRequestHandler = new FailedRequestHandler(); + var client = new RequestClient(httpClient, failedRequestHandler); + var basicRequester = new Requester(client, requestCreator, deserializer); + var rateLimitProvider = new RateLimitProvider(rateLimits); + + return new RateLimitedRequester(basicRequester, rateLimitProvider); + } + + public static IRateLimitedRequester Real(string apiKey) + { + var rateLimits = new Dictionary { { new TimeSpan(1, 0, 0), 10 } }; + + return Real(apiKey, rateLimits); + } + } +} diff --git a/RiotSharp.Test/RequesterTestDoubles.cs b/RiotSharp.Test/RequesterTestDoubles.cs new file mode 100644 index 00000000..f6f0888e --- /dev/null +++ b/RiotSharp.Test/RequesterTestDoubles.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using RiotSharp.Http; +using RiotSharp.Http.Interfaces; + +namespace RiotSharp.Test +{ + public class RequesterTestDoubles + { + public static IRequester Real(string apiKey) + { + var serializer = new RequestContentSerializer(); + var deserializer = new ResponseDeserializer(); + var requestCreator = new RequestCreator(apiKey, serializer); + + var httpClient = new HttpClient(); + var failedRequestHandler = new FailedRequestHandler(); + + var client = new RequestClient(httpClient, failedRequestHandler); + + return new Requester(client, requestCreator, deserializer); + } + } +} diff --git a/RiotSharp.Test/StaticRiotApiTest.cs b/RiotSharp.Test/StaticRiotApiTest.cs index 55eabde6..bc0d0dd2 100644 --- a/RiotSharp.Test/StaticRiotApiTest.cs +++ b/RiotSharp.Test/StaticRiotApiTest.cs @@ -7,6 +7,7 @@ using RiotSharp.StaticDataEndpoint.Champion; using RiotSharp.Http; using System; +using RiotSharp.Http.Interfaces; namespace RiotSharp.Test { @@ -14,10 +15,7 @@ namespace RiotSharp.Test public class StaticRiotApiTest : CommonTestBase { private StaticRiotApi api; - private static RateLimitedRequester requester = new RateLimitedRequester(apiKey, new Dictionary - { - { new TimeSpan(1, 0, 0), 10 } - }); + private static IRateLimitedRequester requester = RateLimitedRequesterTestDoubles.Real(apiKey); public StaticRiotApiTest() { diff --git a/RiotSharp.Test/StatusRiotApiTest.cs b/RiotSharp.Test/StatusRiotApiTest.cs index a212d6ec..50edb559 100644 --- a/RiotSharp.Test/StatusRiotApiTest.cs +++ b/RiotSharp.Test/StatusRiotApiTest.cs @@ -8,7 +8,7 @@ namespace RiotSharp.Test [TestClass] public class StatusRiotApiTest : CommonTestBase { - private static StatusRiotApi api = StatusRiotApi.GetInstance(CommonTestBase.apiKey); + private static StatusRiotApi api = StatusRiotApi.GetInstance(apiKey); [TestMethod] [TestCategory("StatusRiotApi")] @@ -16,7 +16,7 @@ public void GetShardStatus_Test() { EnsureCredibility(() => { - var shardStatus = api.GetShardStatus(StatusRiotApiTestBase.summoner1and2Region); + var shardStatus = api.GetShardStatus(summoner1and2Region); Assert.AreEqual(StatusRiotApiTestBase.platform.ToString().ToLower(), shardStatus.RegionTag); @@ -29,7 +29,7 @@ public void GetShardStatusAsync_Test() { EnsureCredibility(() => { - var shardStatus = api.GetShardStatusAsync(StatusRiotApiTestBase.summoner1and2Region); + var shardStatus = api.GetShardStatusAsync(summoner1and2Region); Assert.AreEqual(StatusRiotApiTestBase.platform.ToString().ToLower(), shardStatus.Result.RegionTag); diff --git a/RiotSharp/Http/FailedRequestHandler.cs b/RiotSharp/Http/FailedRequestHandler.cs new file mode 100644 index 00000000..a139cddd --- /dev/null +++ b/RiotSharp/Http/FailedRequestHandler.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Text; +using RiotSharp.Http.Interfaces; + +namespace RiotSharp.Http +{ + public class FailedRequestHandler : IFailedRequestHandler + { + public void Handle(HttpResponseMessage message) + { + if (message.IsSuccessStatusCode) + { + return; + } + switch (message.StatusCode) + { + case HttpStatusCode.ServiceUnavailable: + throw new RiotSharpException("503, Service unavailable", message.StatusCode); + case HttpStatusCode.InternalServerError: + throw new RiotSharpException("500, Internal server error", message.StatusCode); + case HttpStatusCode.Unauthorized: + throw new RiotSharpException("401, Unauthorized", message.StatusCode); + case HttpStatusCode.BadRequest: + throw new RiotSharpException("400, Bad request", message.StatusCode); + case HttpStatusCode.NotFound: + throw new RiotSharpException("404, Resource not found", message.StatusCode); + case HttpStatusCode.Forbidden: + throw new RiotSharpException("403, Forbidden", message.StatusCode); + case (HttpStatusCode)429: + throw new RiotSharpException("429, Rate Limit Exceeded", message.StatusCode); + default: + throw new RiotSharpException("Unexpeced failure", message.StatusCode); + } + } + } +} diff --git a/RiotSharp/Http/Interfaces/IFailedRequestHandler.cs b/RiotSharp/Http/Interfaces/IFailedRequestHandler.cs new file mode 100644 index 00000000..174ac8c0 --- /dev/null +++ b/RiotSharp/Http/Interfaces/IFailedRequestHandler.cs @@ -0,0 +1,9 @@ +using System.Net.Http; + +namespace RiotSharp.Http.Interfaces +{ + public interface IFailedRequestHandler + { + void Handle(HttpResponseMessage message); + } +} diff --git a/RiotSharp/Http/Interfaces/IRateLimitProvider.cs b/RiotSharp/Http/Interfaces/IRateLimitProvider.cs new file mode 100644 index 00000000..337e7a6a --- /dev/null +++ b/RiotSharp/Http/Interfaces/IRateLimitProvider.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +using RiotSharp.Misc; + +namespace RiotSharp.Http.Interfaces +{ + public interface IRateLimitProvider + { + RateLimiter GetLimiter(Region region); + } +} diff --git a/RiotSharp/Http/Interfaces/IRateLimitedRequester.cs b/RiotSharp/Http/Interfaces/IRateLimitedRequester.cs index 957186f3..7c953151 100644 --- a/RiotSharp/Http/Interfaces/IRateLimitedRequester.cs +++ b/RiotSharp/Http/Interfaces/IRateLimitedRequester.cs @@ -4,100 +4,7 @@ namespace RiotSharp.Http.Interfaces { - public interface IRateLimitedRequester + public interface IRateLimitedRequester : IRequester { - /// - /// Create a get request and send it synchronously to the server. - /// - /// - /// - /// - /// - /// The content of the response. - /// - /// Thrown if an Http error occurs. - /// Contains the Http error code and error message. - /// - string CreateGetRequest(string relativeUrl, Region region, List addedArguments = null, - bool useHttps = true); - - /// - /// Create a get request and send it asynchronously to the server. - /// - /// - /// - /// - /// - /// The content of the response. - /// - /// Thrown if an Http error occurs. - /// Contains the Http error code and error message. - /// - Task CreateGetRequestAsync(string relativeUrl, Region region, List addedArguments = null, - bool useHttps = true); - - /// - /// Create a post request and send it synchronously to the server. - /// - /// - /// - /// - /// - /// - /// The content of the response. - /// - /// Thrown if an Http error occurs. - /// Contains the Http error code and error message. - /// - string CreatePostRequest(string relativeUrl, Region region, string body, - List addedArguments = null, bool useHttps = true); - - /// - /// Create a post request and send it asynchronously to the server. - /// - /// - /// - /// - /// - /// - /// The content of the response. - /// - /// Thrown if an Http error occurs. - /// Contains the Http error code and error message. - /// - Task CreatePostRequestAsync(string relativeUrl, Region region, string body, - List addedArguments = null, bool useHttps = true); - - /// - /// Create a put request and send it synchronously to the server. - /// - /// - /// - /// - /// - /// - /// The content of the response. - /// - /// Thrown if an Http error occurs. - /// Contains the Http error code and error message. - /// - bool CreatePutRequest(string relativeUrl, Region region, string body, List addedArguments = null, - bool useHttps = true); - - /// - /// Create a post request and send it asynchronously to the server. - /// - /// - /// - /// - /// - /// - /// The content of the response. - /// - /// Thrown if an Http error occurs. - /// Contains the Http error code and error message. - /// - Task CreatePutRequestAsync(string relativeUrl, Region region, string body, - List addedArguments = null, bool useHttps = true); } } diff --git a/RiotSharp/Http/Interfaces/IRequestClient.cs b/RiotSharp/Http/Interfaces/IRequestClient.cs new file mode 100644 index 00000000..04dd592d --- /dev/null +++ b/RiotSharp/Http/Interfaces/IRequestClient.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace RiotSharp.Http.Interfaces +{ + public interface IRequestClient + { + /// + /// Send a get request synchronously. + /// + /// + /// + /// Thrown if an Http error occurs. Contains the Http error code and error message. + HttpResponseMessage Get(HttpRequestMessage request); + + /// + /// Send a get request asynchronously. + /// + /// + /// + /// Thrown if an Http error occurs. Contains the Http error code and error message. + Task GetAsync(HttpRequestMessage request); + + /// + /// Send a put request synchronously. + /// + /// + /// + /// Thrown if an Http error occurs. Contains the Http error code and error message. + HttpResponseMessage Put(HttpRequestMessage request); + + /// + /// Send a put request asynchronously. + /// + /// + /// + /// Thrown if an Http error occurs. Contains the Http error code and error message. + Task PutAsync(HttpRequestMessage request); + + /// + /// Send a post request synchronously. + /// + /// + /// + /// Thrown if an Http error occurs. Contains the Http error code and error message. + HttpResponseMessage Post(HttpRequestMessage request); + + /// + /// Send a post request asynchronously. + /// + /// + /// + /// Thrown if an Http error occurs. Contains the Http error code and error message. + Task PostAsync(HttpRequestMessage request); + } +} diff --git a/RiotSharp/Http/Interfaces/IRequestContentSerializer.cs b/RiotSharp/Http/Interfaces/IRequestContentSerializer.cs new file mode 100644 index 00000000..0550fbaa --- /dev/null +++ b/RiotSharp/Http/Interfaces/IRequestContentSerializer.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace RiotSharp.Http.Interfaces +{ + public interface IRequestContentSerializer + { + HttpContent Serialize(object body); + + Task SerializeAsync(object body); + } +} diff --git a/RiotSharp/Http/Interfaces/IRequestCreator.cs b/RiotSharp/Http/Interfaces/IRequestCreator.cs new file mode 100644 index 00000000..61cd17cf --- /dev/null +++ b/RiotSharp/Http/Interfaces/IRequestCreator.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Net.Http; +using RiotSharp.Misc; + +namespace RiotSharp.Http.Interfaces +{ + public interface IRequestCreator + { + HttpRequestMessage CreateGetRequest(Region region, string apiEndpoint, List addedArguments, bool useHttps = true); + + HttpRequestMessage CreatePostRequest(Region region, string apiEndpoint, T body, List addedArguments, bool useHttps); + + HttpRequestMessage CreatePutRequest(Region region, string apiEndpoint, T body, List addedArguments, bool useHttps); + } +} diff --git a/RiotSharp/Http/Interfaces/IRequester.cs b/RiotSharp/Http/Interfaces/IRequester.cs index 5fcf3d27..19d0ef6a 100644 --- a/RiotSharp/Http/Interfaces/IRequester.cs +++ b/RiotSharp/Http/Interfaces/IRequester.cs @@ -1,39 +1,52 @@ -using RiotSharp.Misc; +using System; using System.Collections.Generic; +using System.Text; using System.Threading.Tasks; +using RiotSharp.Misc; namespace RiotSharp.Http.Interfaces { public interface IRequester { /// - /// Create a get request and send it to the server. + /// Creates and sends a get request. Deserializes the response. /// /// /// /// /// - /// The content of the response. + /// The response deserialized to the requested type /// /// Thrown if an Http error occurs. /// Contains the Http error code and error message. /// - string CreateGetRequest(string relativeUrl, Region region, List addedArguments = null, - bool useHttps = true); + T Get(string relativeUrl, Region region, List addedArguments = null, bool useHttps = true); /// - /// Create a get request and send it asynchronously to the server. + /// Creates and asynchronously sends a get request. Deserializes the response. /// /// /// /// /// - /// The content of the response. + /// The response deserialized to the requested type /// /// Thrown if an Http error occurs. /// Contains the Http error code and error message. /// - Task CreateGetRequestAsync(string relativeUrl, Region region, + Task GetAsync(string relativeUrl, Region region, List addedArguments = null, bool useHttps = true); + + T Post(string relativeUrl, Region region, object body, + List addedArguments = null, bool useHttps = true); + + Task PostAsync(string relativeUrl, Region region, object body, + List addedArguments = null, bool useHttps = true); + + bool Put(string relativeUrl, Region region, object body, + List addedArguments = null, bool useHttps = true); + + Task PutAsync(string relativeUrl, Region region, object body, List addedArguments = null, bool useHttps = true); + } } diff --git a/RiotSharp/Http/Interfaces/IResponseDeserializer.cs b/RiotSharp/Http/Interfaces/IResponseDeserializer.cs new file mode 100644 index 00000000..783a8733 --- /dev/null +++ b/RiotSharp/Http/Interfaces/IResponseDeserializer.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace RiotSharp.Http.Interfaces +{ + public interface IResponseDeserializer + { + T DeserializeTo(HttpResponseMessage message); + + Task DeserializeToAsync(HttpResponseMessage message); + } +} diff --git a/RiotSharp/Http/Maps/RegionPlatformMap.cs b/RiotSharp/Http/Maps/RegionPlatformMap.cs new file mode 100644 index 00000000..8a3adae4 --- /dev/null +++ b/RiotSharp/Http/Maps/RegionPlatformMap.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Text; +using RiotSharp.Misc; + +namespace RiotSharp.Http.Maps +{ + public static class RegionPlatformMap + { + + private static readonly IDictionary Map = new Dictionary + { + { Region.br, "br1" }, + { Region.eune , "eun1" }, + { Region.euw , "euw1" }, + { Region.jp , "jp1" }, + { Region.kr , "kr" }, + { Region.lan , "la1" }, + { Region.las , "la2" }, + { Region.na , "na1" }, + { Region.oce , "oc1" }, + { Region.tr , "tr1" }, + { Region.ru , "ru" }, + { Region.global , "global" } + }; + + public static string GetPlatform(Region region) + => Map.ContainsKey(region) ? Map[region] : throw new NotImplementedException("Unsupported region"); + + public static string GetPlatformDomain(Region region) + => $"{GetPlatform(region)}.api.riotgames.com"; + + } +} diff --git a/RiotSharp/Http/RateLimitProvider.cs b/RiotSharp/Http/RateLimitProvider.cs new file mode 100644 index 00000000..558676a9 --- /dev/null +++ b/RiotSharp/Http/RateLimitProvider.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; +using RiotSharp.Http.Interfaces; +using RiotSharp.Misc; + +namespace RiotSharp.Http +{ + public class RateLimitProvider : IRateLimitProvider + { + public readonly IDictionary RateLimits; + + private readonly IDictionary rateLimiters = new Dictionary(); + + public RateLimitProvider(IDictionary rateLimits) + { + RateLimits = rateLimits; + } + + public RateLimiter GetLimiter(Region region) + { + if (!rateLimiters.ContainsKey(region)) + rateLimiters[region] = new RateLimiter(RateLimits); + return rateLimiters[region]; + } + } +} diff --git a/RiotSharp/Http/RateLimitedRequester.cs b/RiotSharp/Http/RateLimitedRequester.cs index eabe41a7..7726445e 100644 --- a/RiotSharp/Http/RateLimitedRequester.cs +++ b/RiotSharp/Http/RateLimitedRequester.cs @@ -1,135 +1,65 @@ -using RiotSharp.Http.Interfaces; +using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; +using RiotSharp.Http.Interfaces; using RiotSharp.Misc; -using System; namespace RiotSharp.Http { - /// - /// A requester with a rate limiter - /// - public class RateLimitedRequester : RequesterBase, IRateLimitedRequester + public class RateLimitedRequester : IRateLimitedRequester { - public readonly IDictionary RateLimits; - public RateLimitedRequester(string apiKey, IDictionary rateLimits) : base(apiKey) + private readonly IRequester requester; + private readonly IRateLimitProvider limitProvider; + + public RateLimitedRequester(IRequester requester, IRateLimitProvider limitProvider) { - RateLimits = rateLimits; + this.requester = requester; + this.limitProvider = limitProvider; } - private readonly Dictionary rateLimiters = new Dictionary(); - - #region Public Methods - - public string CreateGetRequest(string relativeUrl, Region region, List addedArguments = null, + public T Get(string relativeUrl, Region region, List addedArguments = null, bool useHttps = true) { - rootDomain = GetPlatformDomain(region); - - var request = PrepareRequest(relativeUrl, addedArguments, useHttps, HttpMethod.Get); - - GetRateLimiter(region).HandleRateLimit(); - - using (var response = Get(request)) - { - return GetResponseContent(response); - } + limitProvider.GetLimiter(region).HandleRateLimit(); + return requester.Get(relativeUrl, region, addedArguments, useHttps); } - public async Task CreateGetRequestAsync(string relativeUrl, Region region, List addedArguments = null, + public async Task GetAsync(string relativeUrl, Region region, List addedArguments = null, bool useHttps = true) { - rootDomain = GetPlatformDomain(region); - - var request = PrepareRequest(relativeUrl, addedArguments, useHttps, HttpMethod.Get); - - await GetRateLimiter(region).HandleRateLimitAsync(); - - using (var response = await GetAsync(request)) - { - return await GetResponseContentAsync(response); - } + await limitProvider.GetLimiter(region).HandleRateLimitAsync(); + return await requester.GetAsync(relativeUrl, region, addedArguments, useHttps); } - public string CreatePostRequest(string relativeUrl, Region region, string body, + public T Post(string relativeUrl, Region region, object body, List addedArguments = null, bool useHttps = true) { - rootDomain = GetPlatformDomain(region); - - var request = PrepareRequest(relativeUrl, addedArguments, useHttps, HttpMethod.Post); - request.Content = new StringContent(body, Encoding.UTF8, "application/json"); - - GetRateLimiter(region).HandleRateLimit(); - - using (var response = Post(request)) - { - return GetResponseContent(response); - } + limitProvider.GetLimiter(region).HandleRateLimit(); + return requester.Post(relativeUrl, region, body, addedArguments, useHttps); } - public async Task CreatePostRequestAsync(string relativeUrl, Region region, string body, + public async Task PostAsync(string relativeUrl, Region region, object body, List addedArguments = null, bool useHttps = true) { - rootDomain = GetPlatformDomain(region); - - var request = PrepareRequest(relativeUrl, addedArguments, useHttps, HttpMethod.Post); - request.Content = new StringContent(body, Encoding.UTF8, "application/json"); - - await GetRateLimiter(region).HandleRateLimitAsync(); - - using (var response = await PostAsync(request)) - { - return await GetResponseContentAsync(response); - } - } - - public bool CreatePutRequest(string relativeUrl, Region region, string body, List addedArguments = null, - bool useHttps = true) - { - rootDomain = GetPlatformDomain(region); - - var request = PrepareRequest(relativeUrl, addedArguments, useHttps, HttpMethod.Put); - request.Content = new StringContent(body, Encoding.UTF8, "application/json"); - - GetRateLimiter(region).HandleRateLimit(); - - using (var response = Put(request)) - { - return (int)response.StatusCode >= 200 && (int)response.StatusCode < 300; - } + limitProvider.GetLimiter(region).HandleRateLimit(); + return await requester.PostAsync(relativeUrl, region, body, addedArguments, useHttps); } - public async Task CreatePutRequestAsync(string relativeUrl, Region region, string body, + public bool Put(string relativeUrl, Region region, object body, List addedArguments = null, bool useHttps = true) { - rootDomain = GetPlatformDomain(region); - - var request = PrepareRequest(relativeUrl, addedArguments, useHttps, HttpMethod.Put); - request.Content = new StringContent(body, Encoding.UTF8, "application/json"); - - await GetRateLimiter(region).HandleRateLimitAsync(); - - using (var response = await PutAsync(request)) - { - return (int)response.StatusCode >= 200 && (int)response.StatusCode < 300; - } + limitProvider.GetLimiter(region).HandleRateLimit(); + return requester.Put(relativeUrl, region, body, addedArguments, useHttps); } - #endregion - - /// - /// Returns the respective region's RateLimiter, creating it if needed. - /// - /// - /// - private RateLimiter GetRateLimiter(Region region) + public async Task PutAsync(string relativeUrl, Region region, object body, + List addedArguments = null, bool useHttps = true) { - if (!rateLimiters.ContainsKey(region)) - rateLimiters[region] = new RateLimiter(RateLimits); - return rateLimiters[region]; + limitProvider.GetLimiter(region).HandleRateLimit(); + return await requester.PutAsync(relativeUrl, region, body, addedArguments, useHttps); } } } diff --git a/RiotSharp/Http/RateLimiter.cs b/RiotSharp/Http/RateLimiter.cs index 1b1d6b9e..50b22870 100644 --- a/RiotSharp/Http/RateLimiter.cs +++ b/RiotSharp/Http/RateLimiter.cs @@ -7,7 +7,7 @@ [assembly: InternalsVisibleTo("RiotSharp.Test")] namespace RiotSharp.Http { - internal class RateLimiter + public class RateLimiter { /// Semaphore to prevent multiple requests from interferering with each other's rate limit /// calculations. diff --git a/RiotSharp/Http/RequestClient.cs b/RiotSharp/Http/RequestClient.cs new file mode 100644 index 00000000..24a1f542 --- /dev/null +++ b/RiotSharp/Http/RequestClient.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using RiotSharp.Http.Interfaces; + +namespace RiotSharp.Http +{ + public class RequestClient : IRequestClient + { + private readonly HttpClient client; + private readonly IFailedRequestHandler failureHandler; + + public RequestClient(HttpClient client, IFailedRequestHandler failureHandler) + { + this.client = client; + this.failureHandler = failureHandler; + } + + public HttpResponseMessage Get(HttpRequestMessage request) + => GetAsync(request).Result; + + public async Task GetAsync(HttpRequestMessage request) + { + var response = await client.GetAsync(request.RequestUri); + failureHandler.Handle(response); + return response; + } + + public HttpResponseMessage Put(HttpRequestMessage request) + => PutAsync(request).Result; + + public async Task PutAsync(HttpRequestMessage request) + { + var response = await client.PutAsync(request.RequestUri, request.Content); + failureHandler.Handle(response); + return response; + } + + public HttpResponseMessage Post(HttpRequestMessage request) + => PostAsync(request).Result; + + public async Task PostAsync(HttpRequestMessage request) + { + var response = await client.PostAsync(request.RequestUri, request.Content); + failureHandler.Handle(response); + return response; + } + + } +} diff --git a/RiotSharp/Http/RequestContentSerializer.cs b/RiotSharp/Http/RequestContentSerializer.cs new file mode 100644 index 00000000..3178c636 --- /dev/null +++ b/RiotSharp/Http/RequestContentSerializer.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using RiotSharp.Http.Interfaces; + +namespace RiotSharp.Http +{ + public class RequestContentSerializer : IRequestContentSerializer + { + public HttpContent Serialize(object body) + { + var json = JsonConvert.SerializeObject(body, Settings); + return new StringContent(json, Encoding.UTF8, "application/json"); + } + + public async Task SerializeAsync(object body) + { + var json = await Task.Run(() => JsonConvert.SerializeObject(body, Settings)); + return new StringContent(json, Encoding.UTF8, "application/json"); + } + + private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore + }; + } +} diff --git a/RiotSharp/Http/RequestCreator.cs b/RiotSharp/Http/RequestCreator.cs new file mode 100644 index 00000000..921b0c31 --- /dev/null +++ b/RiotSharp/Http/RequestCreator.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using Newtonsoft.Json; +using RiotSharp.Http.Interfaces; +using RiotSharp.Http.Maps; +using RiotSharp.Misc; + +namespace RiotSharp.Http +{ + public class RequestCreator : IRequestCreator + { + private readonly string apiKey; + private readonly IRequestContentSerializer contentSerializer; + + public RequestCreator(string apiKey, IRequestContentSerializer contentSerializer) + { + this.apiKey = apiKey; + this.contentSerializer = contentSerializer; + } + + public HttpRequestMessage CreateGetRequest(Region region, string apiEndpoint, List addedArguments, bool useHttps = true) + { + var url = BuildUrl(region, apiEndpoint, addedArguments, useHttps); + return new HttpRequestMessage(HttpMethod.Get, url); + } + + public HttpRequestMessage CreatePostRequest(Region region, string apiEndpoint, T body, List addedArguments, bool useHttps) + { + var url = BuildUrl(region, apiEndpoint, addedArguments, useHttps); + return new HttpRequestMessage(HttpMethod.Post, url) + { + Content = contentSerializer.Serialize(body) + //Content = new StringContent(body, Encoding.UTF8, "application/json"), + }; + } + + public HttpRequestMessage CreatePutRequest(Region region, string apiEndpoint, T body, + List addedArguments, bool useHttps) + { + var url = BuildUrl(region, apiEndpoint, addedArguments, useHttps); + return new HttpRequestMessage(HttpMethod.Put, url) + { + Content = contentSerializer.Serialize(body) + }; + } + + + private string BuildUrl(Region region, string apiEndpoint, List addedArguments, bool useHttps) + { + var scheme = useHttps ? "https" : "http"; + var domain = RegionPlatformMap.GetPlatformDomain(region); + var arguments = BuildArgumentString(addedArguments); + + return $"{scheme}://{domain}{apiEndpoint}?{arguments}"; + } + + private string BuildArgumentString(IEnumerable arguments) + => string.Join("&", arguments.Concat(GetApiKeyParameter()).Where(IsNotEmpty)); + + private IEnumerable GetApiKeyParameter() + => new[] { $"api_key={apiKey}" }; + + private static bool IsNotEmpty(string argument) + => argument != string.Empty; + } +} diff --git a/RiotSharp/Http/Requester.cs b/RiotSharp/Http/Requester.cs index 999a30b2..e61b1c22 100644 --- a/RiotSharp/Http/Requester.cs +++ b/RiotSharp/Http/Requester.cs @@ -1,41 +1,88 @@ -using RiotSharp.Http.Interfaces; -using RiotSharp.Misc; -using System; +using System; using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; +using System.Text; using System.Threading.Tasks; +using RiotSharp.Http.Interfaces; +using RiotSharp.Misc; namespace RiotSharp.Http { /// - /// A requester without a rate limiter. + /// An alternative requester without a rate limiter. /// - public class Requester : RequesterBase, IRequester + public class Requester : IRequester { - public Requester(string apiKey) : base(apiKey) + private readonly IRequestClient client; + private readonly IRequestCreator requestCreator; + private readonly IResponseDeserializer responseDeserializer; + + private static List NoArguments() => new List(); + + public Requester(IRequestClient client, IRequestCreator requestCreator, IResponseDeserializer responseDeserializer) + { + this.client = client; + this.requestCreator = requestCreator; + this.responseDeserializer = responseDeserializer; + } + + public T Get( + string relativeUrl, + Region region, + List addedArguments = null, + bool useHttps = true) { + var arguments = addedArguments ?? NoArguments(); + var request = requestCreator.CreateGetRequest(region, relativeUrl, arguments, useHttps); + var response = client.Get(request); + return responseDeserializer.DeserializeTo(response); } - #region Public Methods - public string CreateGetRequest(string relativeUrl, Region region, List addedArguments = null, + public async Task GetAsync( + string relativeUrl, + Region region, + List addedArguments = null, bool useHttps = true) { - rootDomain = GetPlatformDomain(region); - var request = PrepareRequest(relativeUrl, addedArguments, useHttps, HttpMethod.Get); - var response = Get(request); - return GetResponseContent(response); + var arguments = addedArguments ?? NoArguments(); + var request = requestCreator.CreateGetRequest(region, relativeUrl, arguments, useHttps); + var response = await client.GetAsync(request); + return await responseDeserializer.DeserializeToAsync(response); + } + + public T Post(string relativeUrl, Region region, object body, + List addedArguments = null, bool useHttps = true) + { + var arguments = addedArguments ?? NoArguments(); + var request = requestCreator.CreatePostRequest(region, relativeUrl, body, arguments, useHttps); + var response = client.Post(request); + return responseDeserializer.DeserializeTo(response); + } + + public async Task PostAsync(string relativeUrl, Region region, object body, + List addedArguments = null, bool useHttps = true) + { + var arguments = addedArguments ?? NoArguments(); + var request = requestCreator.CreatePostRequest(region, relativeUrl, body, arguments, useHttps); + var response = await client.PostAsync(request); + return await responseDeserializer.DeserializeToAsync(response); + } + + public bool Put(string relativeUrl, Region region, object body, + List addedArguments = null, bool useHttps = true) + { + var arguments = addedArguments ?? NoArguments(); + var request = requestCreator.CreatePostRequest(region, relativeUrl, body, arguments, useHttps); + var response = client.Post(request); + return response.IsSuccessStatusCode; } - public async Task CreateGetRequestAsync(string relativeUrl, Region region, + public async Task PutAsync(string relativeUrl, Region region, object body, List addedArguments = null, bool useHttps = true) { - rootDomain = GetPlatformDomain(region); - var request = PrepareRequest(relativeUrl, addedArguments, useHttps, HttpMethod.Get); - var response = await GetAsync(request); - return await GetResponseContentAsync(response); + var arguments = addedArguments ?? NoArguments(); + var request = requestCreator.CreatePutRequest(region, relativeUrl, body, arguments, useHttps); + var response = await client.PostAsync(request); + return response.IsSuccessStatusCode; } - #endregion } } diff --git a/RiotSharp/Http/ResponseDeserializer.cs b/RiotSharp/Http/ResponseDeserializer.cs new file mode 100644 index 00000000..21b82428 --- /dev/null +++ b/RiotSharp/Http/ResponseDeserializer.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using RiotSharp.Http.Interfaces; + +namespace RiotSharp.Http +{ + public class ResponseDeserializer : IResponseDeserializer + { + public async Task DeserializeToAsync(HttpResponseMessage message) + { + var json = await message.Content.ReadAsStringAsync(); + return await Task.Run(() => JsonConvert.DeserializeObject(json)); + } + + public T DeserializeTo(HttpResponseMessage message) + => DeserializeToAsync(message).Result; + } +} diff --git a/RiotSharp/RiotApi.cs b/RiotSharp/RiotApi.cs index 70c6b9b7..aa882389 100644 --- a/RiotSharp/RiotApi.cs +++ b/RiotSharp/RiotApi.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using RiotSharp.MatchListEndpoint; using RiotSharp.Misc; @@ -63,7 +64,7 @@ public class RiotApi : IRiotApi private const int MaxNrSummoners = 40; private const int MaxNrMasteryPages = 40; - private readonly IRateLimitedRequester requester; + private readonly IRequester requester; private static RiotApi instance; #endregion @@ -109,30 +110,39 @@ public static RiotApi GetInstance(string apiKey, int rateLimitPer10s, int rateLi /// The instance of RiotApi. public static RiotApi GetInstance(string apiKey, IDictionary rateLimits) { + /* todo is this logic required? if (instance == null || Requesters.RiotApiRequester == null || apiKey != Requesters.RiotApiRequester.ApiKey || !rateLimits.Equals(Requesters.RiotApiRequester.RateLimits)) { instance = new RiotApi(apiKey, rateLimits); - } - return instance; + } */ + return instance ?? (instance = new RiotApi(apiKey, rateLimits)); } private RiotApi(string apiKey, IDictionary rateLimits) { - Requesters.RiotApiRequester = new RateLimitedRequester(apiKey, rateLimits); - requester = Requesters.RiotApiRequester; + var serializer = new RequestContentSerializer(); + var deserializer = new ResponseDeserializer(); + var requestCreator = new RequestCreator(apiKey, serializer); + var httpClient = new HttpClient(); + var failedRequestHandler = new FailedRequestHandler(); + var client = new RequestClient(httpClient, failedRequestHandler); + var basicRequester = new Requester(client, requestCreator, deserializer); + var rateLimitProvider = new RateLimitProvider(rateLimits); + + requester = new RateLimitedRequester(basicRequester, rateLimitProvider); + + Requesters.RiotApiRequester = (RateLimitedRequester) requester; } /// /// Dependency injection constructor /// - /// - public RiotApi(IRateLimitedRequester rateLimitedRequester) + /// + public RiotApi(IRequester requester) { - if (rateLimitedRequester == null) - throw new ArgumentNullException(nameof(rateLimitedRequester)); - requester = rateLimitedRequester; + this.requester = requester ?? throw new ArgumentNullException(nameof(requester)); } #pragma warning disable CS1591 @@ -140,224 +150,176 @@ public RiotApi(IRateLimitedRequester rateLimitedRequester) #region Summoner public Summoner GetSummonerByAccountId(Region region, long accountId) { - var json = requester.CreateGetRequest( - string.Format(SummonerRootUrl + SummonerByAccountIdUrl, accountId), region); - var obj = JsonConvert.DeserializeObject(json); - if (obj != null) - { - obj.Region = region; - } - return obj; + var url = string.Format(SummonerRootUrl + SummonerByAccountIdUrl, accountId); + var summoner = requester.Get(url, region); + return SummonerWithRegion(summoner, region); } public async Task GetSummonerByAccountIdAsync(Region region, long accountId) { - var json = await requester.CreateGetRequestAsync( - string.Format(SummonerRootUrl + SummonerByAccountIdUrl, accountId), region); - var obj = (await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json))); - if (obj != null) - { - obj.Region = region; - } - return obj; + var url = string.Format(SummonerRootUrl + SummonerByAccountIdUrl, accountId); + var summoner = await requester.GetAsync(url, region); + return SummonerWithRegion(summoner, region); } public Summoner GetSummonerBySummonerId(Region region, long summonerId) { - var json = requester.CreateGetRequest( - string.Format(SummonerRootUrl + SummonerBySummonerIdUrl, summonerId), region); - var obj = JsonConvert.DeserializeObject(json); - if (obj != null) - { - obj.Region = region; - } - return obj; + var url = string.Format(SummonerRootUrl + SummonerBySummonerIdUrl, summonerId); + var summoner = requester.Get(url, region); + return SummonerWithRegion(summoner, region); } public async Task GetSummonerBySummonerIdAsync(Region region, long summonerId) { - var json = await requester.CreateGetRequestAsync( - string.Format(SummonerRootUrl + SummonerBySummonerIdUrl, summonerId), region); - var obj = (await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json))); - if (obj != null) - { - obj.Region = region; - } - return obj; + var url = string.Format(SummonerRootUrl + SummonerBySummonerIdUrl, summonerId); + var summoner = await requester.GetAsync(url, region); + return SummonerWithRegion(summoner, region); } public Summoner GetSummonerByName(Region region, string summonerName) { - var json = requester.CreateGetRequest( - string.Format(SummonerRootUrl + SummonerByNameUrl, summonerName), region); - var obj = JsonConvert.DeserializeObject(json); - if (obj != null) - { - obj.Region = region; - } - return obj; + var url = string.Format(SummonerRootUrl + SummonerByNameUrl, summonerName); + var summoner = requester.Get(url, region); + return SummonerWithRegion(summoner, region); } public async Task GetSummonerByNameAsync(Region region, string summonerName) { - var json = await requester.CreateGetRequestAsync( - string.Format(SummonerRootUrl + SummonerByNameUrl, summonerName), region); - var obj = (await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json))); - if (obj != null) + var url = string.Format(SummonerRootUrl + SummonerByNameUrl, summonerName); + var summoner = await requester.GetAsync(url, region); + return SummonerWithRegion(summoner, region); + } + + public Summoner SummonerWithRegion(Summoner summoner, Region region) + { + if (summoner != null) { - obj.Region = region; + summoner.Region = region; } - return obj; + return summoner; } #endregion #region Champion public List GetChampions(Region region, bool freeToPlay = false) { - var json = requester.CreateGetRequest(PlatformRootUrl + ChampionsUrl, region, - new List { string.Format("freeToPlay={0}", freeToPlay ? "true" : "false") }); - return JsonConvert.DeserializeObject(json).Champions; + var url = PlatformRootUrl + ChampionsUrl; + var arguments = new List{$"freeToPlay={freeToPlay.ToString().ToLower()}" }; + return requester.Get(url, region, arguments).Champions; } public async Task> GetChampionsAsync(Region region, bool freeToPlay = false) { - var json = await requester.CreateGetRequestAsync(PlatformRootUrl + ChampionsUrl, region, - new List { string.Format("freeToPlay={0}", freeToPlay ? "true" : "false") }); - return (await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json))).Champions; + var url = PlatformRootUrl + ChampionsUrl; + var arguments = new List { $"freeToPlay={freeToPlay.ToString().ToLower()}" }; + return (await requester.GetAsync(url, region, arguments)).Champions; } public Champion GetChampion(Region region, int championId) { - var json = requester.CreateGetRequest( - PlatformRootUrl + ChampionsUrl + string.Format(IdUrl, championId), region); - return JsonConvert.DeserializeObject(json); + var url = PlatformRootUrl + ChampionsUrl + string.Format(IdUrl, championId); + return requester.Get(url, region); } public async Task GetChampionAsync(Region region, int championId) { - var json = await requester.CreateGetRequestAsync(PlatformRootUrl + ChampionsUrl + string.Format(IdUrl, championId), region); - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json)); + var url = PlatformRootUrl + ChampionsUrl + string.Format(IdUrl, championId); + return await requester.GetAsync(url, region); + } #endregion #region Masteries public List GetMasteryPages(Region region, long summonerId) { - var json = requester.CreateGetRequest(PlatformRootUrl + string.Format(MasteriesUrl, summonerId), region); - - var masteries = JsonConvert.DeserializeObject(json); - return masteries.Pages; + var url = PlatformRootUrl + string.Format(MasteriesUrl, summonerId); + return requester.Get(url, region).Pages; } public async Task> GetMasteryPagesAsync(Region region, long summonerId) { - var json = await requester.CreateGetRequestAsync(PlatformRootUrl + string.Format(MasteriesUrl, summonerId), region); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json).Pages); + var url = PlatformRootUrl + string.Format(MasteriesUrl, summonerId); + return (await requester.GetAsync(url, region)).Pages; } #endregion #region Runes public List GetRunePages(Region region, long summonerId) { - var json = requester.CreateGetRequest(PlatformRootUrl + string.Format(RunesUrl, summonerId), region); - - var runes = JsonConvert.DeserializeObject(json); - return runes.Pages; + var url = PlatformRootUrl + string.Format(RunesUrl, summonerId); + return requester.Get(url, region).Pages; } public async Task> GetRunePagesAsync(Region region, long summonerId) { - var json = await requester.CreateGetRequestAsync(PlatformRootUrl + string.Format(RunesUrl, summonerId), - region); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json).Pages); + var url = PlatformRootUrl + string.Format(RunesUrl, summonerId); + return (await requester.GetAsync(url, region)).Pages; } #endregion #region League public List GetLeagues(Region region, long summonerId) { - var json = requester.CreateGetRequest(LeagueRootUrl + string.Format(LeagueBySummonerUrl, summonerId), - region); - return JsonConvert.DeserializeObject>(json); + var url = LeagueRootUrl + string.Format(LeagueBySummonerUrl, summonerId); + return requester.Get>(url, region); } public async Task> GetLeaguesAsync(Region region, long summonerId) { - var json = await requester.CreateGetRequestAsync( - LeagueRootUrl + string.Format(LeagueBySummonerUrl, summonerId), region); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject>(json)); + var url = LeagueRootUrl + string.Format(LeagueBySummonerUrl, summonerId); + return await requester.GetAsync>(url, region); } - + public List GetLeaguePositions(Region region, long summonerId) { - var json = requester.CreateGetRequest( - LeagueRootUrl + string.Format(LeaguePositionBySummonerUrl, summonerId), - region); - - return JsonConvert.DeserializeObject>(json); + var url = LeagueRootUrl + string.Format(LeaguePositionBySummonerUrl, summonerId); + return requester.Get>(url, region); } - + public async Task> GetLeaguePositionsAsync(Region region, long summonerId) { - var json = await requester.CreateGetRequestAsync( - LeagueRootUrl + string.Format(LeaguePositionBySummonerUrl, summonerId), region); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject>(json)); + var url = LeagueRootUrl + string.Format(LeaguePositionBySummonerUrl, summonerId); + return await requester.GetAsync>(url, region); } public League GetChallengerLeague(Region region, string queue) { - var json = requester.CreateGetRequest(LeagueRootUrl + string.Format(LeagueChallengerUrl, queue), region); - return JsonConvert.DeserializeObject(json); + var url = LeagueRootUrl + string.Format(LeagueChallengerUrl, queue); + return requester.Get(url, region); } public async Task GetChallengerLeagueAsync(Region region, string queue) { - var json = await requester.CreateGetRequestAsync(LeagueRootUrl + string.Format(LeagueChallengerUrl, queue), - region); - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json)); + var url = LeagueRootUrl + string.Format(LeagueChallengerUrl, queue); + return await requester.GetAsync(url, region); } public League GetMasterLeague(Region region, string queue) { - var json = requester.CreateGetRequest(LeagueRootUrl + string.Format(LeagueMasterUrl, queue), region); - return JsonConvert.DeserializeObject(json); + var url = LeagueRootUrl + string.Format(LeagueMasterUrl, queue); + return requester.Get(url, region); } public async Task GetMasterLeagueAsync(Region region, string queue) { - var json = await requester.CreateGetRequestAsync(LeagueRootUrl + string.Format(LeagueMasterUrl, queue), - region); - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json)); + var url = LeagueRootUrl + string.Format(LeagueMasterUrl, queue); + return await requester.GetAsync(url, region); } + #endregion + #region Match public MatchDetail GetMatch(Region region, long matchId, bool includeTimeline = false) { - var json = requester.CreateGetRequest( - string.Format(MatchRootUrl, region.ToString()) + string.Format(IdUrl, matchId), - region, - includeTimeline - ? new List { string.Format("includeTimeline={0}", includeTimeline.ToString().ToLower()) } - : null); - return JsonConvert.DeserializeObject(json); + var url = string.Format(MatchRootUrl, region.ToString()) + string.Format(IdUrl, matchId); + var arguments = includeTimeline ? new List { "includeTimeline=false" } : new List(); + return requester.Get(url, region, arguments); } - #endregion - #region Match public async Task GetMatchAsync(Region region, long matchId, bool includeTimeline = false) { - var json = await requester.CreateGetRequestAsync( - string.Format(MatchRootUrl, region.ToString()) + string.Format(IdUrl, matchId), - region, - includeTimeline - ? new List {string.Format("includeTimeline={0}", includeTimeline)} - : null); - return await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); + var url = string.Format(MatchRootUrl, region.ToString()) + string.Format(IdUrl, matchId); + var arguments = includeTimeline ? new List { "includeTimeline=false" } : new List(); + return await requester.GetAsync(url, region, arguments); } public MatchList GetMatchList(Region region, long summonerId, @@ -367,35 +329,32 @@ public MatchList GetMatchList(Region region, long summonerId, { var addedArguments = new List { - string.Format("beginIndex={0}", beginIndex), - string.Format("endIndex={0}", endIndex), + $"beginIndex={beginIndex}", + $"endIndex={endIndex}", }; if (beginTime != null) { - addedArguments.Add(string.Format("beginTime={0}", beginTime.Value.ToLong())); + addedArguments.Add($"beginTime={beginTime.Value.ToLong()}"); } if (endTime != null) { - addedArguments.Add(string.Format("endTime={0}", endTime.Value.ToLong())); + addedArguments.Add($"endTime={endTime.Value.ToLong()}"); } if (championIds != null) { - addedArguments.Add(string.Format("championIds={0}", Util.BuildIdsString(championIds))); + addedArguments.Add($"championIds={Util.BuildIdsString(championIds)}"); } if (rankedQueues != null) { - addedArguments.Add(string.Format("rankedQueues={0}", Util.BuildQueuesString(rankedQueues))); + addedArguments.Add($"rankedQueues={Util.BuildQueuesString(rankedQueues)}"); } if (seasons != null) { - addedArguments.Add(string.Format("seasons={0}", Util.BuildSeasonString(seasons))); + addedArguments.Add($"seasons={Util.BuildSeasonString(seasons)}"); } - var json = requester.CreateGetRequest( - string.Format(MatchListRootUrl, region.ToString()) + string.Format(IdUrl, summonerId), - region, - addedArguments); - return JsonConvert.DeserializeObject(json); + var url = string.Format(MatchListRootUrl, region.ToString()) + string.Format(IdUrl, summonerId); + return requester.Get(url, region, addedArguments); } public async Task GetMatchListAsync(Region region, long summonerId, @@ -429,104 +388,86 @@ public async Task GetMatchListAsync(Region region, long summonerId, addedArguments.Add(string.Format("seasons={0}", Util.BuildSeasonString(seasons))); } - var json = await requester.CreateGetRequestAsync( - string.Format(MatchListRootUrl, region.ToString()) + string.Format(IdUrl, summonerId), - region, - addedArguments); - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json)); + var url = string.Format(MatchListRootUrl, region.ToString()) + string.Format(IdUrl, summonerId); + + return await requester.GetAsync(url, region, addedArguments); } public List GetRecentGames(Region region, long summonerId) { - var json = requester.CreateGetRequest( - string.Format(GameRootUrl, region) + string.Format(RecentGamesUrl, summonerId), - region); - return JsonConvert.DeserializeObject(json).Games; + var url = string.Format(GameRootUrl, region) + string.Format(RecentGamesUrl, summonerId); + return requester.Get(url, region).Games; } public async Task> GetRecentGamesAsync(Region region, long summonerId) { - var json = await requester.CreateGetRequestAsync( - string.Format(GameRootUrl, region) + string.Format(RecentGamesUrl, summonerId), - region); - return (await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json))).Games; + var url = string.Format(GameRootUrl, region) + string.Format(RecentGamesUrl, summonerId); + return (await requester.GetAsync(url, region)).Games; } #endregion #region Spectator public CurrentGame GetCurrentGame(Region region, long summonerId) { - var json = requester.CreateGetRequest(SpectatorRootUrl + string.Format(CurrentGameUrl, summonerId), region); - return JsonConvert.DeserializeObject(json); + var url = SpectatorRootUrl + string.Format(CurrentGameUrl, summonerId); + return requester.Get(url, region); } - + public async Task GetCurrentGameAsync(Region region, long summonerId) { - var json = await requester.CreateGetRequestAsync(SpectatorRootUrl + string.Format(CurrentGameUrl, summonerId), region); - return (await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json))); + var url = SpectatorRootUrl + string.Format(CurrentGameUrl, summonerId); + return await requester.GetAsync(url, region); } public FeaturedGames GetFeaturedGames(Region region) { - var json = requester.CreateGetRequest(SpectatorRootUrl + FeaturedGamesUrl, region); - return JsonConvert.DeserializeObject(json); + var url = SpectatorRootUrl + FeaturedGamesUrl; + return requester.Get(url, region); } public async Task GetFeaturedGamesAsync(Region region) { - var json = await requester.CreateGetRequestAsync(SpectatorRootUrl + FeaturedGamesUrl, region); - return (await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json))); + var url = SpectatorRootUrl + FeaturedGamesUrl; + return await requester.GetAsync(url, region); } #endregion #region Champion Mastery public ChampionMastery GetChampionMastery(Region region, long summonerId, long championId) { - var requestUrl = string.Format(ChampionMasteryBySummonerUrl, summonerId, championId); - - var json = requester.CreateGetRequest(ChampionMasteryRootUrl + requestUrl, region); - return JsonConvert.DeserializeObject(json); + var url = ChampionMasteryRootUrl + string.Format(ChampionMasteryBySummonerUrl, summonerId, championId); + return requester.Get(url, region); } public async Task GetChampionMasteryAsync(Region region, long summonerId, long championId) { - var requestUrl = string.Format(ChampionMasteryBySummonerUrl, summonerId, championId); - - var json = await requester.CreateGetRequestAsync(ChampionMasteryRootUrl + requestUrl, region); - return (await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json))); + var url = ChampionMasteryRootUrl + string.Format(ChampionMasteryBySummonerUrl, summonerId, championId); + return await requester.GetAsync(url, region); } public List GetChampionMasteries(Region region, long summonerId) { - var requestUrl = string.Format(ChampionMasteriesBySummonerUrl, summonerId); + var url = ChampionMasteryRootUrl + string.Format(ChampionMasteriesBySummonerUrl, summonerId); + return requester.Get>(url, region); - var json = requester.CreateGetRequest(ChampionMasteryRootUrl + requestUrl, region); - return JsonConvert.DeserializeObject>(json); } public async Task> GetChampionMasteriesAsync(Region region, long summonerId) { - var requestUrl = string.Format(ChampionMasteriesBySummonerUrl, summonerId); - - var json = await requester.CreateGetRequestAsync(ChampionMasteryRootUrl + requestUrl, region); - return (await Task.Factory.StartNew(() => JsonConvert.DeserializeObject>(json))); + var url = ChampionMasteryRootUrl + string.Format(ChampionMasteriesBySummonerUrl, summonerId); + return await requester.GetAsync>(url, region); } public int GetTotalChampionMasteryScore(Region region, long summonerId) { - var requestUrl = string.Format(ChampionMasteryTotalScoreBySummonerUrl, summonerId); - - var json = requester.CreateGetRequest(ChampionMasteryRootUrl + requestUrl, region); - return JsonConvert.DeserializeObject(json); + var url = ChampionMasteryRootUrl + string.Format(ChampionMasteryTotalScoreBySummonerUrl, summonerId); + return requester.Get(url, region); } public async Task GetTotalChampionMasteryScoreAsync(Region region, long summonerId) { - var requestUrl = string.Format(ChampionMasteryTotalScoreBySummonerUrl, summonerId); - - var json = requester.CreateGetRequest(ChampionMasteryRootUrl + requestUrl, region); - return (await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json))); + var url = ChampionMasteryRootUrl + string.Format(ChampionMasteryTotalScoreBySummonerUrl, summonerId); + return await requester.GetAsync(url, region); } #endregion diff --git a/RiotSharp/StaticRiotApi.cs b/RiotSharp/StaticRiotApi.cs index 84da2441..d6881c98 100644 --- a/RiotSharp/StaticRiotApi.cs +++ b/RiotSharp/StaticRiotApi.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using RiotSharp.Misc; using RiotSharp.StaticDataEndpoint.Champion; @@ -83,27 +84,29 @@ public class StaticRiotApi : IStaticRiotApi private const string IdUrl = "/{0}"; private const string TagsParameter = "tags={0}"; - private IRateLimitedRequester requester; + private readonly IRequester requester; private ICache cache; public readonly TimeSpan DefaultSlidingExpirationTime = new TimeSpan(1, 0, 0); internal TimeSpan SlidingExpirationTime; private static StaticRiotApi instance; - #endregion - + private static string instanceApiKey; + #endregion + /// /// Get the instance of StaticRiotApi. /// /// The api key. + /// + /// /// The instance of StaticRiotApi. public static StaticRiotApi GetInstance(string apiKey, bool useCache = true, TimeSpan? slidingExpirationTime = null) { - if (instance == null || - Requesters.StaticApiRequester == null || - apiKey != Requesters.StaticApiRequester.ApiKey) + if (instance == null || instanceApiKey != apiKey) { + instanceApiKey = apiKey; instance = new StaticRiotApi(apiKey, useCache, slidingExpirationTime); } return instance; @@ -111,20 +114,22 @@ public static StaticRiotApi GetInstance(string apiKey, bool useCache = true, private StaticRiotApi(string apiKey, bool useCache = true, TimeSpan? slidingExpirationTime = null) { - Requesters.StaticApiRequester = new RateLimitedRequester(apiKey, new Dictionary - { - { new TimeSpan(1, 0, 0), 10 } - }); - requester = Requesters.StaticApiRequester; - if (useCache) - cache = new Cache(); - else - cache = new PassThroughCache(); + var rateLimits = new Dictionary{ {new TimeSpan(1, 0, 0), 10} }; - if (slidingExpirationTime == null) - SlidingExpirationTime = DefaultSlidingExpirationTime; - else - SlidingExpirationTime = slidingExpirationTime.Value; + var serializer = new RequestContentSerializer(); + var deserializer = new ResponseDeserializer(); + var requestCreator = new RequestCreator(apiKey, serializer); + var httpClient = new HttpClient(); + var failedRequestHandler = new FailedRequestHandler(); + var client = new RequestClient(httpClient, failedRequestHandler); + var basicRequester = new Requester(client, requestCreator, deserializer); + var rateLimitProvider = new RateLimitProvider(rateLimits); + + requester = new RateLimitedRequester(basicRequester, rateLimitProvider); + Requesters.StaticApiRequester = (RateLimitedRequester)requester; + + cache = useCache ? (ICache) new Cache() : new PassThroughCache(); + SlidingExpirationTime = slidingExpirationTime ?? DefaultSlidingExpirationTime; } /// @@ -132,15 +137,12 @@ private StaticRiotApi(string apiKey, bool useCache = true, TimeSpan? slidingExpi /// /// /// - public StaticRiotApi(IRateLimitedRequester requester, ICache cache, TimeSpan? slidingExpirationTime = null) + /// + public StaticRiotApi(IRequester requester, ICache cache, TimeSpan? slidingExpirationTime = null) { this.requester = requester ?? throw new ArgumentNullException(nameof(requester)); this.cache = cache ?? throw new ArgumentNullException(nameof(cache)); - - if (slidingExpirationTime == null) - SlidingExpirationTime = DefaultSlidingExpirationTime; - else - SlidingExpirationTime = slidingExpirationTime.Value; + SlidingExpirationTime = slidingExpirationTime ?? DefaultSlidingExpirationTime; } #pragma warning disable CS1691 @@ -151,14 +153,14 @@ public ChampionListStatic GetChampions(Region region, ChampionData championData var wrapper = cache.Get(ChampionsCacheKey); if (wrapper == null || language != wrapper.Language || championData != wrapper.ChampionData) { - var json = requester.CreateGetRequest(StaticDataRootUrl + ChampionsUrl, region, + var url = StaticDataRootUrl + ChampionsUrl; + var champs = requester.Get(url, region, new List { string.Format("locale={0}", language.ToString()), championData == ChampionData.Basic ? string.Empty : string.Format(TagsParameter, championData.ToString().ToLower()) }); - var champs = JsonConvert.DeserializeObject(json); wrapper = new ChampionListStaticWrapper(champs, language, championData); cache.Add(ChampionsCacheKey, wrapper, SlidingExpirationTime); } @@ -173,7 +175,7 @@ public async Task GetChampionsAsync(Region region, { return wrapper.ChampionListStatic; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + ChampionsUrl, region, + var champs = await requester.GetAsync(StaticDataRootUrl + ChampionsUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -181,8 +183,6 @@ public async Task GetChampionsAsync(Region region, string.Empty : string.Format(TagsParameter, championData.ToString().ToLower()) }); - var champs = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); wrapper = new ChampionListStaticWrapper(champs, language, championData); cache.Add(ChampionsCacheKey, wrapper, SlidingExpirationTime); return wrapper.ChampionListStatic; @@ -206,7 +206,7 @@ public ChampionStatic GetChampion(Region region, int championId, } else { - var json = requester.CreateGetRequest( + var champ = requester.Get( StaticDataRootUrl + string.Format(ChampionByIdUrl, championId), region, new List { @@ -215,7 +215,6 @@ public ChampionStatic GetChampion(Region region, int championId, string.Empty : string.Format(TagsParameter, championData.ToString().ToLower()) }); - var champ = JsonConvert.DeserializeObject(json); cache.Add(ChampionByIdCacheKey + championId, new ChampionStaticWrapper(champ, language, championData), SlidingExpirationTime); return champ; @@ -237,7 +236,7 @@ public async Task GetChampionAsync(Region region, int championId { return listWrapper.ChampionListStatic.Champions.Values.FirstOrDefault(c => c.Id == championId); } - var json = await requester.CreateGetRequestAsync( + var champ = await requester.GetAsync( StaticDataRootUrl + string.Format(ChampionByIdUrl, championId), region, new List { @@ -246,8 +245,6 @@ public async Task GetChampionAsync(Region region, int championId string.Empty : string.Format(TagsParameter, championData.ToString().ToLower()) }); - var champ = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); cache.Add(ChampionByIdCacheKey + championId, new ChampionStaticWrapper(champ, language, championData), SlidingExpirationTime); return champ; @@ -261,7 +258,7 @@ public ItemListStatic GetItems(Region region, ItemData itemData = ItemData.All, var wrapper = cache.Get(ItemsCacheKey); if (wrapper == null || language != wrapper.Language || itemData != wrapper.ItemData) { - var json = requester.CreateGetRequest(StaticDataRootUrl + ItemsUrl, region, + var items = requester.Get(StaticDataRootUrl + ItemsUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -269,7 +266,6 @@ public ItemListStatic GetItems(Region region, ItemData itemData = ItemData.All, string.Empty : string.Format(TagsParameter, itemData.ToString().ToLower()) }); - var items = JsonConvert.DeserializeObject(json); wrapper = new ItemListStaticWrapper(items, language, itemData); cache.Add(ItemsCacheKey, wrapper, SlidingExpirationTime); } @@ -284,7 +280,7 @@ public async Task GetItemsAsync(Region region, ItemData itemData { return wrapper.ItemListStatic; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + ItemsUrl, region, + var items = await requester.GetAsync(StaticDataRootUrl + ItemsUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -292,8 +288,6 @@ public async Task GetItemsAsync(Region region, ItemData itemData string.Empty : string.Format(TagsParameter, itemData.ToString().ToLower()) }); - var items = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); wrapper = new ItemListStaticWrapper(items, language, itemData); cache.Add(ItemsCacheKey, wrapper, SlidingExpirationTime); return wrapper.ItemListStatic; @@ -323,7 +317,7 @@ public ItemStatic GetItem(Region region, int itemId, ItemData itemData = ItemDat } else { - var json = requester.CreateGetRequest( + var item = requester.Get( StaticDataRootUrl + string.Format(ItemByIdUrl, itemId), region, new List { @@ -332,7 +326,6 @@ public ItemStatic GetItem(Region region, int itemId, ItemData itemData = ItemDat string.Empty : string.Format(TagsParameter, itemData.ToString().ToLower()) }); - var item = JsonConvert.DeserializeObject(json); cache.Add(ItemByIdCacheKey + itemId, new ItemStaticWrapper(item, language, itemData), SlidingExpirationTime); return item; @@ -354,7 +347,7 @@ public async Task GetItemAsync(Region region, int itemId, ItemData i return listWrapper.ItemListStatic.Items.ContainsKey(itemId) ? listWrapper.ItemListStatic.Items[itemId] : null; } - var json = await requester.CreateGetRequestAsync( + var item = await requester.GetAsync( StaticDataRootUrl + string.Format(ItemByIdUrl, itemId), region, new List { @@ -363,8 +356,6 @@ public async Task GetItemAsync(Region region, int itemId, ItemData i string.Empty : string.Format(TagsParameter, itemData.ToString().ToLower()) }); - var item = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); cache.Add(ItemByIdCacheKey + itemId, new ItemStaticWrapper(item, language, itemData), SlidingExpirationTime); return item; } @@ -380,12 +371,11 @@ public LanguageStringsStatic GetLanguageStrings(Region region, Language language return wrapper.LanguageStringsStatic; } - var json = requester.CreateGetRequest(StaticDataRootUrl + LanguageStringsUrl, region, + var languageStrings = requester.Get(StaticDataRootUrl + LanguageStringsUrl, region, new List { string.Format("locale={0}", language.ToString()), string.Format("version={0}", version) }); - var languageStrings = JsonConvert.DeserializeObject(json); cache.Add(LanguageStringsCacheKey, new LanguageStringsStaticWrapper(languageStrings, language, version), SlidingExpirationTime); @@ -402,13 +392,11 @@ public async Task GetLanguageStringsAsync(Region region, return wrapper.LanguageStringsStatic; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + LanguageStringsUrl, region, + var languageStrings = await requester.GetAsync(StaticDataRootUrl + LanguageStringsUrl, region, new List { string.Format("locale={0}", language.ToString()), string.Format("version={0}", version) }); - var languageStrings = await Task.Factory.StartNew(() - => JsonConvert.DeserializeObject(json)); cache.Add(LanguageStringsCacheKey, new LanguageStringsStaticWrapper(languageStrings, language, version), SlidingExpirationTime); @@ -426,8 +414,7 @@ public List GetLanguages(Region region) return wrapper; } - var json = requester.CreateGetRequest(StaticDataRootUrl + LanguagesUrl, region); - var languages = JsonConvert.DeserializeObject>(json); + var languages = requester.Get>(StaticDataRootUrl + LanguagesUrl, region); cache.Add(LanguagesCacheKey, languages, SlidingExpirationTime); @@ -442,9 +429,7 @@ public async Task> GetLanguagesAsync(Region region) return wrapper; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + LanguagesUrl, region); - var languages = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject>(json)); + var languages = await requester.GetAsync>(StaticDataRootUrl + LanguagesUrl, region); cache.Add(LanguagesCacheKey, languages, SlidingExpirationTime); @@ -461,12 +446,11 @@ public List GetMaps(Region region, Language language = Language.en_US return wrapper.MapsStatic.Data.Values.ToList(); } - var json = requester.CreateGetRequest(StaticDataRootUrl + MapsUrl, region, + var maps = requester.Get(StaticDataRootUrl + MapsUrl, region, new List { string.Format("locale={0}", language.ToString()), string.Format("version={0}", version) }); - var maps = JsonConvert.DeserializeObject(json); cache.Add(MapsCacheKey, new MapsStaticWrapper(maps, language, version), SlidingExpirationTime); @@ -482,13 +466,11 @@ public async Task> GetMapsAsync(Region region, Language language return wrapper.MapsStatic.Data.Values.ToList(); } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + MapsUrl, region, + var maps = await requester.GetAsync(StaticDataRootUrl + MapsUrl, region, new List { string.Format("locale={0}", language.ToString()), string.Format("version={0}", version) }); - var maps = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); cache.Add(MapsCacheKey, new MapsStaticWrapper(maps, language, version), SlidingExpirationTime); @@ -503,7 +485,7 @@ public MasteryListStatic GetMasteries(Region region, MasteryData masteryData = M var wrapper = cache.Get(MasteriesCacheKey); if (wrapper == null || language != wrapper.Language || masteryData != wrapper.MasteryData) { - var json = requester.CreateGetRequest(StaticDataRootUrl + MasteriesUrl, region, + var masteries = requester.Get(StaticDataRootUrl + MasteriesUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -511,7 +493,6 @@ public MasteryListStatic GetMasteries(Region region, MasteryData masteryData = M string.Empty : string.Format(TagsParameter, masteryData.ToString().ToLower()) }); - var masteries = JsonConvert.DeserializeObject(json); wrapper = new MasteryListStaticWrapper(masteries, language, masteryData); cache.Add(MasteriesCacheKey, wrapper, SlidingExpirationTime); } @@ -526,7 +507,7 @@ public async Task GetMasteriesAsync(Region region, { return wrapper.MasteryListStatic; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + MasteriesUrl, region, + var masteries = await requester.GetAsync(StaticDataRootUrl + MasteriesUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -534,8 +515,6 @@ public async Task GetMasteriesAsync(Region region, string.Empty : string.Format(TagsParameter, masteryData.ToString().ToLower()) }); - var masteries = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); wrapper = new MasteryListStaticWrapper(masteries, language, masteryData); cache.Add(MasteriesCacheKey, wrapper, SlidingExpirationTime); return wrapper.MasteryListStatic; @@ -565,7 +544,7 @@ public MasteryStatic GetMastery(Region region, int masteryId, MasteryData master } else { - var json = requester.CreateGetRequest( + var mastery = requester.Get( StaticDataRootUrl + string.Format(MasteryByIdUrl, masteryId), region, new List { @@ -573,7 +552,6 @@ public MasteryStatic GetMastery(Region region, int masteryId, MasteryData master masteryData == MasteryData.Basic ? string.Empty : string.Format(TagsParameter, masteryData.ToString().ToLower()) }); - var mastery = JsonConvert.DeserializeObject(json); cache.Add(MasteryByIdCacheKey + masteryId, new MasteryStaticWrapper(mastery, language, masteryData), SlidingExpirationTime); return mastery; @@ -595,7 +573,7 @@ public async Task GetMasteryAsync(Region region, int masteryId, return listWrapper.MasteryListStatic.Masteries.ContainsKey(masteryId) ? listWrapper.MasteryListStatic.Masteries[masteryId] : null; } - var json = await requester.CreateGetRequestAsync( + var mastery = await requester.GetAsync( StaticDataRootUrl + string.Format(MasteryByIdUrl, masteryId), region, new List { @@ -603,8 +581,6 @@ public async Task GetMasteryAsync(Region region, int masteryId, masteryData == MasteryData.Basic ? string.Empty : string.Format(TagsParameter, masteryData.ToString().ToLower()) }); - var mastery = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); cache.Add(MasteryByIdCacheKey + masteryId, new MasteryStaticWrapper(mastery, language, masteryData), SlidingExpirationTime); return mastery; @@ -617,11 +593,10 @@ public ProfileIconListStatic GetProfileIcons(Region region, Language language = var wrapper = cache.Get(ProfileIconsCacheKey); if (wrapper == null || language != wrapper.Language) { - var json = requester.CreateGetRequest(StaticDataRootUrl + ProfileIconsUrl, region, + var profileIcons = requester.Get(StaticDataRootUrl + ProfileIconsUrl, region, new List { string.Format("locale={0}", language.ToString()) }); - var profileIcons = JsonConvert.DeserializeObject(json); wrapper = new ProfileIconsStaticWrapper(profileIcons, language); cache.Add(ProfileIconsCacheKey, wrapper, SlidingExpirationTime); } @@ -635,12 +610,11 @@ public async Task GetProfileIconsAsync(Region region, Lan { return wrapper.ProfileIconListStatic; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + ProfileIconsUrl, region, + var profileIcons = await requester.GetAsync(StaticDataRootUrl + ProfileIconsUrl, region, new List { string.Format("locale={0}", language.ToString()) }); - var profileIcons = JsonConvert.DeserializeObject(json); wrapper = new ProfileIconsStaticWrapper(profileIcons, language); cache.Add(ProfileIconsCacheKey, wrapper, SlidingExpirationTime); return wrapper.ProfileIconListStatic; @@ -656,8 +630,7 @@ public RealmStatic GetRealm(Region region) return wrapper.RealmStatic; } - var json = requester.CreateGetRequest(StaticDataRootUrl + RealmsUrl, region); - var realm = JsonConvert.DeserializeObject(json); + var realm = requester.Get(StaticDataRootUrl + RealmsUrl, region); cache.Add(RealmsCacheKey, new RealmStaticWrapper(realm), SlidingExpirationTime); @@ -672,8 +645,7 @@ public async Task GetRealmAsync(Region region) return wrapper.RealmStatic; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + RealmsUrl, region); - var realm = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json)); + var realm = await requester.GetAsync(StaticDataRootUrl + RealmsUrl, region); cache.Add(RealmsCacheKey, new RealmStaticWrapper(realm), SlidingExpirationTime); @@ -688,7 +660,7 @@ public RuneListStatic GetRunes(Region region, RuneData runeData = RuneData.All var wrapper = cache.Get(RunesCacheKey); if (wrapper == null || language != wrapper.Language || runeData != wrapper.RuneData) { - var json = requester.CreateGetRequest(StaticDataRootUrl + RunesUrl, region, + var runes = requester.Get(StaticDataRootUrl + RunesUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -696,7 +668,6 @@ public RuneListStatic GetRunes(Region region, RuneData runeData = RuneData.All string.Empty : string.Format(TagsParameter, runeData.ToString().ToLower()) }); - var runes = JsonConvert.DeserializeObject(json); wrapper = new RuneListStaticWrapper(runes, language, runeData); cache.Add(RunesCacheKey, wrapper, SlidingExpirationTime); } @@ -711,7 +682,7 @@ public async Task GetRunesAsync(Region region, RuneData runeData { return wrapper.RuneListStatic; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + RunesUrl, region, + var runes = await requester.GetAsync(StaticDataRootUrl + RunesUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -719,8 +690,6 @@ public async Task GetRunesAsync(Region region, RuneData runeData string.Empty : string.Format(TagsParameter, runeData.ToString().ToLower()) }); - var runes = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); wrapper = new RuneListStaticWrapper(runes, language, runeData); cache.Add(RunesCacheKey, wrapper, SlidingExpirationTime); return wrapper.RuneListStatic; @@ -739,18 +708,11 @@ public RuneStatic GetRune(Region region, int runeId, RuneData runeData = RuneDat var listWrapper = cache.Get(RunesCacheKey); if (listWrapper != null && listWrapper.Language == language && listWrapper.RuneData == runeData) { - if (listWrapper.RuneListStatic.Runes.ContainsKey(runeId)) - { - return listWrapper.RuneListStatic.Runes[runeId]; - } - else - { - return null; - } + return listWrapper.RuneListStatic.Runes.ContainsKey(runeId) ? listWrapper.RuneListStatic.Runes[runeId] : null; } else { - var json = requester.CreateGetRequest( + var rune = requester.Get( StaticDataRootUrl + string.Format(RuneByIdUrl, runeId), region, new List { @@ -759,7 +721,6 @@ public RuneStatic GetRune(Region region, int runeId, RuneData runeData = RuneDat string.Empty : string.Format(TagsParameter, runeData.ToString().ToLower()) }); - var rune = JsonConvert.DeserializeObject(json); cache.Add(RuneByIdCacheKey + runeId, new RuneStaticWrapper(rune, language, runeData), SlidingExpirationTime); return rune; @@ -781,7 +742,7 @@ public async Task GetRuneAsync(Region region, int runeId, RuneData r return listWrapper.RuneListStatic.Runes.ContainsKey(runeId) ? listWrapper.RuneListStatic.Runes[runeId] : null; } - var json = await requester.CreateGetRequestAsync( + var rune = await requester.GetAsync( StaticDataRootUrl + string.Format(RuneByIdUrl, runeId), region, new List { @@ -790,8 +751,6 @@ public async Task GetRuneAsync(Region region, int runeId, RuneData r string.Empty : string.Format(TagsParameter, runeData.ToString().ToLower()) }); - var rune = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); cache.Add(RuneByIdCacheKey + runeId, new RuneStaticWrapper(rune, language, runeData), SlidingExpirationTime); return rune; } @@ -804,7 +763,7 @@ public SummonerSpellListStatic GetSummonerSpells(Region region, var wrapper = cache.Get(SummonerSpellsCacheKey); if (wrapper == null || wrapper.Language != language || wrapper.SummonerSpellData != summonerSpellData) { - var json = requester.CreateGetRequest(StaticDataRootUrl + SummonerSpellsUrl, region, + var spells = requester.Get(StaticDataRootUrl + SummonerSpellsUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -812,7 +771,6 @@ public SummonerSpellListStatic GetSummonerSpells(Region region, string.Empty : string.Format(TagsParameter, summonerSpellData.ToString().ToLower()) }); - var spells = JsonConvert.DeserializeObject(json); wrapper = new SummonerSpellListStaticWrapper(spells, language, summonerSpellData); cache.Add(SummonerSpellsCacheKey, wrapper, SlidingExpirationTime); } @@ -827,7 +785,7 @@ public async Task GetSummonerSpellsAsync(Region region, { return wrapper.SummonerSpellListStatic; } - var json = await requester.CreateGetRequestAsync(StaticDataRootUrl + SummonerSpellsUrl, region, + var spells = await requester.GetAsync(StaticDataRootUrl + SummonerSpellsUrl, region, new List { string.Format("locale={0}", language.ToString()), @@ -835,8 +793,6 @@ public async Task GetSummonerSpellsAsync(Region region, string.Empty : string.Format(TagsParameter, summonerSpellData.ToString().ToLower()) }); - var spells = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); wrapper = new SummonerSpellListStaticWrapper(spells, language, summonerSpellData); cache.Add(SummonerSpellsCacheKey, wrapper, SlidingExpirationTime); return wrapper.SummonerSpellListStatic; @@ -868,7 +824,7 @@ public SummonerSpellStatic GetSummonerSpell(Region region, int summonerSpellId, } else { - var json = requester.CreateGetRequest( + var spell = requester.Get( StaticDataRootUrl + string.Format(SummonerSpellByIdUrl, summonerSpellId), region, new List { @@ -877,7 +833,6 @@ public SummonerSpellStatic GetSummonerSpell(Region region, int summonerSpellId, string.Empty : string.Format(TagsParameter, summonerSpellData.ToString().ToLower()) }); - var spell = JsonConvert.DeserializeObject(json); cache.Add(SummonerSpellByIdCacheKey + summonerSpellId, new SummonerSpellStaticWrapper(spell, language, summonerSpellData), SlidingExpirationTime); return spell; @@ -901,7 +856,7 @@ public async Task GetSummonerSpellAsync(Region region, int return listWrapper.SummonerSpellListStatic.SummonerSpells.ContainsKey(summonerSpellId.ToString()) ? listWrapper.SummonerSpellListStatic.SummonerSpells[summonerSpellId.ToString()] : null; } - var json = await requester.CreateGetRequestAsync( + var spell = await requester.GetAsync( StaticDataRootUrl + string.Format(SummonerSpellByIdUrl, summonerSpellId), region, new List { @@ -910,8 +865,6 @@ public async Task GetSummonerSpellAsync(Region region, int string.Empty : string.Format(TagsParameter, summonerSpellData.ToString().ToLower()) }); - var spell = await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json)); cache.Add(SummonerSpellByIdCacheKey + summonerSpellId, new SummonerSpellStaticWrapper(spell, language, summonerSpellData), SlidingExpirationTime); return spell; @@ -927,8 +880,7 @@ public List GetVersions(Region region) return wrapper; } - var json = requester.CreateGetRequest(StaticDataRootUrl + VersionsUrl, region); - var version = JsonConvert.DeserializeObject>(json); + var version = requester.Get>(StaticDataRootUrl + VersionsUrl, region); cache.Add(VersionsCacheKey, version, SlidingExpirationTime); @@ -943,9 +895,7 @@ public async Task> GetVersionsAsync(Region region) return wrapper; } - var json = - await requester.CreateGetRequestAsync(StaticDataRootUrl + VersionsUrl, region); - var version = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject>(json)); + var version = await requester.GetAsync>(StaticDataRootUrl + VersionsUrl, region); cache.Add(VersionsCacheKey, version, SlidingExpirationTime); diff --git a/RiotSharp/StatusRiotApi.cs b/RiotSharp/StatusRiotApi.cs index 819a4f37..8f742e08 100644 --- a/RiotSharp/StatusRiotApi.cs +++ b/RiotSharp/StatusRiotApi.cs @@ -6,25 +6,36 @@ using System.Threading.Tasks; using RiotSharp.Misc; using System; +using System.Net.Http; namespace RiotSharp { - public class StatusRiotApi : IStatusRiotApi + public partial class StatusRiotApi : IStatusRiotApi { - #region Private Fields - private const string StatusRootUrl = "/lol/status/v3/shard-data"; - private const string PlatformSubdomain = "{0}."; + private readonly IRequester requester; - private const string RootDomain = "api.riotgames.com"; + public StatusRiotApi(IRequester requester) + { + this.requester = requester; + } + + public ShardStatus GetShardStatus(Region region) + { + return requester.Get(StatusRootUrl, region); + } - private IRequester requester; + public async Task GetShardStatusAsync(Region region) + { + return await requester.GetAsync(StatusRootUrl, region); + } + } + public partial class StatusRiotApi + { private static StatusRiotApi instance; - #endregion - /// /// Get the instance of StatusRiotApi. /// @@ -32,40 +43,22 @@ public class StatusRiotApi : IStatusRiotApi /// The instance of StatusRiotApi. public static StatusRiotApi GetInstance(string apiKey) { - if (instance == null) - instance = new StatusRiotApi(apiKey); - return instance; + return instance ?? (instance = new StatusRiotApi(apiKey)); } private StatusRiotApi(string apiKey) { - Requesters.StatusApiRequester = new Requester(apiKey); - requester = Requesters.StatusApiRequester; - } - - public StatusRiotApi(IRequester requester) - { - if (requester == null) - throw new ArgumentNullException(nameof(requester)); - this.requester = requester; - } - - #region Public Methods + var serializer = new RequestContentSerializer(); + var deserializer = new ResponseDeserializer(); + var requestCreator = new RequestCreator(apiKey, serializer); - public ShardStatus GetShardStatus(Region region) - { - var json = requester.CreateGetRequest(StatusRootUrl, region, null, true); + var httpClient = new HttpClient(); + var failedRequestHandler = new FailedRequestHandler(); - return JsonConvert.DeserializeObject(json); - } + var client = new RequestClient(httpClient, failedRequestHandler); - public async Task GetShardStatusAsync(Region region) - { - var json = await requester.CreateGetRequestAsync(StatusRootUrl, region, null, true); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json)); + requester = new Requester(client, requestCreator, deserializer); + Requesters.StatusApiRequester = (Requester) requester; } - - #endregion } } diff --git a/RiotSharp/SummonerEndpoint/SummonerBase.cs b/RiotSharp/SummonerEndpoint/SummonerBase.cs index 0d95353f..510b4518 100644 --- a/RiotSharp/SummonerEndpoint/SummonerBase.cs +++ b/RiotSharp/SummonerEndpoint/SummonerBase.cs @@ -20,7 +20,7 @@ public class SummonerBase private const string IdUrl = "/{0}"; - private IRateLimitedRequester requester; + private readonly IRequester requester; public Region Region { get; set; } internal SummonerBase() @@ -29,7 +29,7 @@ internal SummonerBase() } //summoner base not default constructor - internal SummonerBase(string id, string name, IRateLimitedRequester requester, Region region) + internal SummonerBase(string id, string name, IRequester requester, Region region) { this.requester = requester; Region = region; @@ -60,10 +60,8 @@ internal SummonerBase(string id, string name, IRateLimitedRequester requester, R /// A list of the 10 most recent games. public List GetRecentGames() { - var json = requester.CreateGetRequest( - string.Format(GameRootUrl, Region) + string.Format(RecentGamesUrl, Id), - Region); - return JsonConvert.DeserializeObject(json).Games; + var url = string.Format(GameRootUrl, Region) + string.Format(RecentGamesUrl, Id); + return requester.Get(url, Region).Games; } /// @@ -72,11 +70,8 @@ public List GetRecentGames() /// A list of the 10 most recent games. public async Task> GetRecentGamesAsync() { - var json = await requester.CreateGetRequestAsync( - string.Format(GameRootUrl, Region) + string.Format(RecentGamesUrl, Id), - Region); - return (await Task.Factory.StartNew(() => - JsonConvert.DeserializeObject(json))).Games; + var url = string.Format(GameRootUrl, Region) + string.Format(RecentGamesUrl, Id); + return (await requester.GetAsync(url, Region)).Games; } } } diff --git a/RiotSharp/TournamentRiotApi.cs b/RiotSharp/TournamentRiotApi.cs index 1d23fc46..d0d901f2 100644 --- a/RiotSharp/TournamentRiotApi.cs +++ b/RiotSharp/TournamentRiotApi.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using RiotSharp.Misc; using RiotSharp.TournamentEndpoint.Enums; @@ -31,17 +32,29 @@ public class TournamentRiotApi : ITournamentRiotApi private const string GetMatchDetailUrl = "/for-tournament/{0}"; private static TournamentRiotApi instance; + private static string instanceApiKey; + private static IDictionary instanceRateLimits; - private readonly IRateLimitedRequester requester; + private readonly IRequester requester; private string tournamentRootUrl; #endregion private TournamentRiotApi(string apiKey, IDictionary rateLimits, bool useStub = false) { - Requesters.TournamentApiRequester = new RateLimitedRequester(apiKey, rateLimits); - requester = Requesters.TournamentApiRequester; SetTournamentRootUrl(useStub); + + var serializer = new RequestContentSerializer(); + var deserializer = new ResponseDeserializer(); + var requestCreator = new RequestCreator(apiKey, serializer); + var httpClient = new HttpClient(); + var failedRequestHandler = new FailedRequestHandler(); + var client = new RequestClient(httpClient, failedRequestHandler); + var basicRequester = new Requester(client, requestCreator, deserializer); + var rateLimitProvider = new RateLimitProvider(rateLimits); + + requester = new RateLimitedRequester(basicRequester, rateLimitProvider); + Requesters.TournamentApiRequester = (RateLimitedRequester)requester; } /// @@ -51,7 +64,7 @@ private TournamentRiotApi(string apiKey, IDictionary rateLimits, /// If true, the tournament stub will be used for requests. /// Useful for testing purposes. /// - public TournamentRiotApi(IRateLimitedRequester rateLimitedRequester, bool useStub = false) + public TournamentRiotApi(IRequester rateLimitedRequester, bool useStub = false) { if (rateLimitedRequester == null) throw new ArgumentNullException(nameof(rateLimitedRequester)); @@ -97,9 +110,11 @@ public static TournamentRiotApi GetInstance(string apiKey, IDictionary(); if (instance == null || Requesters.TournamentApiRequester == null || - apiKey != Requesters.TournamentApiRequester.ApiKey || - !rateLimits.Equals(Requesters.TournamentApiRequester.RateLimits)) + apiKey != instanceApiKey || + !rateLimits.Equals(instanceRateLimits)) { + instanceApiKey = apiKey; + instanceRateLimits = rateLimits; instance = new TournamentRiotApi(apiKey, rateLimits); } return instance; @@ -127,10 +142,8 @@ public int CreateProvider(Region region, string url) { "url", url }, { "region", region.ToString().ToUpper() } }; - var json = requester.CreatePostRequest(tournamentRootUrl + CreateProviderUrl, Region.global, - JsonConvert.SerializeObject(body)); - - return int.Parse(json); + var relativeUrl = tournamentRootUrl + CreateProviderUrl; + return requester.Post(relativeUrl, Region.global, body); } public async Task CreateProviderAsync(Region region, string url) @@ -140,12 +153,8 @@ public async Task CreateProviderAsync(Region region, string url) { "url", url }, { "region", region.ToString().ToUpper() } }; - var json = - await - requester.CreatePostRequestAsync(tournamentRootUrl + CreateProviderUrl, Region.global, - JsonConvert.SerializeObject(body)); - - return int.Parse(json); + var relativeUrl = tournamentRootUrl + CreateProviderUrl; + return await requester.PostAsync(relativeUrl, Region.global, body); } public int CreateTournament(int providerId, string name) @@ -155,24 +164,19 @@ public int CreateTournament(int providerId, string name) { "name", name }, { "providerId", providerId } }; - var json = requester.CreatePostRequest(tournamentRootUrl + CreateTournamentUrl, Region.global, - JsonConvert.SerializeObject(body)); - - return int.Parse(json); + var relativeUrl = tournamentRootUrl + CreateTournamentUrl; + return requester.Post(relativeUrl, Region.global, body); } public async Task CreateTournamentAsync(int providerId, string name) { - var body = new Dictionary { + var body = new Dictionary + { { "name", name }, { "providerId", providerId } }; - var json = - await - requester.CreatePostRequestAsync(tournamentRootUrl + CreateTournamentUrl, Region.global, - JsonConvert.SerializeObject(body)); - - return int.Parse(json); + var relativeUrl = tournamentRootUrl + CreateTournamentUrl; + return await requester.PostAsync(relativeUrl, Region.global, body); } public List CreateTournamentCodes(int tournamentId, int count, int teamSize, TournamentSpectatorType spectatorType, @@ -190,21 +194,15 @@ public List CreateTournamentCodes(int tournamentId, int count, int teamS { "mapType", mapType }, { "metadata", metadata } }; - var json = requester.CreatePostRequest(tournamentRootUrl + CreateCodesUrl, Region.global, - JsonConvert.SerializeObject(body, null, - new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore - }), - new List - { - string.Format("tournamentId={0}", tournamentId), - string.Format("count={0}", count) - }); - - var tournamentCodes = JsonConvert.DeserializeObject>(json); - - return tournamentCodes; + + var arguments = new List + { + $"tournamentId={tournamentId}", + $"count={count}" + }; + + var url = tournamentRootUrl + CreateCodesUrl; + return requester.Post>(url, Region.global, body, arguments); } public async Task> CreateTournamentCodesAsync(int tournamentId, int count, int teamSize, @@ -222,79 +220,55 @@ public async Task> CreateTournamentCodesAsync(int tournamentId, int { "mapType", mapType }, { "metadata", metadata } }; - var json = await requester.CreatePostRequestAsync(tournamentRootUrl + CreateCodesUrl, Region.global, - JsonConvert.SerializeObject(body, null, - new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore - }), - new List - { - string.Format("tournamentId={0}", tournamentId), - string.Format("count={0}", count) - }); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject>(json)); + + var arguments = new List + { + $"tournamentId={tournamentId}", + $"count={count}" + }; + + var url = tournamentRootUrl + CreateCodesUrl; + return await requester.PostAsync>(url, Region.global, body, arguments); } public TournamentCodeDetail GetTournamentCodeDetails(string tournamentCode) { - var json = requester.CreateGetRequest(tournamentRootUrl + string.Format(GetCodesUrl, tournamentCode), - Region.global); - var tournamentCodeDetails = JsonConvert.DeserializeObject(json); - - return tournamentCodeDetails; + var url = tournamentRootUrl + string.Format(GetCodesUrl, tournamentCode); + return requester.Get(url, Region.global); } public async Task GetTournamentCodeDetailsAsync(string tournamentCode) { - var json = - await - requester.CreateGetRequestAsync(tournamentRootUrl + string.Format(GetCodesUrl, tournamentCode), - Region.global); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json)); + var url = tournamentRootUrl + string.Format(GetCodesUrl, tournamentCode); + return await requester.GetAsync(url, Region.global); } - + public List GetTournamentLobbyEvents(string tournamentCode) { - var json = requester.CreateGetRequest(tournamentRootUrl + string.Format(LobbyEventUrl, tournamentCode), - Region.global); - var lobbyEventsDTO = JsonConvert.DeserializeObject>>(json); - - return lobbyEventsDTO["eventList"]; + var url = tournamentRootUrl + string.Format(LobbyEventUrl, tournamentCode); + return requester.Get>>(url, Region.global)["eventList"]; } public async Task> GetTournamentLobbyEventsAsync(string tournamentCode) { - var json = - await - requester.CreateGetRequestAsync(tournamentRootUrl + string.Format(LobbyEventUrl, tournamentCode), - Region.global); - - return - await - Task.Factory.StartNew(() => - JsonConvert.DeserializeObject>>(json)["eventList"] - ); + var url = tournamentRootUrl + string.Format(LobbyEventUrl, tournamentCode); + return (await requester.GetAsync>>(url, Region.global))["eventList"]; } public bool UpdateTournamentCode(string tournamentCode, List allowedParticipantIds = null, TournamentSpectatorType? spectatorType = null, TournamentPickType? pickType = null, TournamentMapType? mapType= null) { + var url = tournamentRootUrl + string.Format(PutCodeUrl, tournamentCode); var body = BuildTournamentUpdateBody(allowedParticipantIds, spectatorType, pickType, mapType); - - return requester.CreatePutRequest(tournamentRootUrl + string.Format(PutCodeUrl, tournamentCode), Region.global, - JsonConvert.SerializeObject(body)); + return requester.Put(url, Region.global, body); } public async Task UpdateTournamentCodeAsync(string tournamentCode, List allowedParticipantIds = null, TournamentSpectatorType? spectatorType = null, TournamentPickType? pickType = null, TournamentMapType? mapType = null) { + var url = tournamentRootUrl + string.Format(PutCodeUrl, tournamentCode); var body = BuildTournamentUpdateBody(allowedParticipantIds, spectatorType, pickType, mapType); - - return await requester.CreatePutRequestAsync(tournamentRootUrl + string.Format(PutCodeUrl, tournamentCode), - Region.global, JsonConvert.SerializeObject(body)); + return await requester.PutAsync(url, Region.global, body); } #endregion @@ -303,55 +277,37 @@ public async Task UpdateTournamentCodeAsync(string tournamentCode, List - { - string.Format("tournamentCode={0}", tournamentCode), - string.Format("includeTimeline={0}", includeTimeline) - }); - - var matchDetail = JsonConvert.DeserializeObject(json); - - return matchDetail; + var url = string.Format(MatchRootUrl, region) + string.Format(GetMatchDetailUrl, matchId); + var arguments = new List + { + $"tournamentCode={tournamentCode}", + $"includeTimeline={includeTimeline}" + }; + return requester.Get(url, region, arguments); } public async Task GetTournamentMatchAsync(Region region, long matchId, string tournamentCode, bool includeTimeline) { - var json = - await - requester.CreateGetRequestAsync( - string.Format(MatchRootUrl, region) + string.Format(GetMatchDetailUrl, matchId), region, - new List - { - string.Format("tournamentCode={0}", tournamentCode), - string.Format("includeTimeline={0}", includeTimeline) - }); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject(json)); + var url = string.Format(MatchRootUrl, region) + string.Format(GetMatchDetailUrl, matchId); + var arguments = new List + { + $"tournamentCode={tournamentCode}", + $"includeTimeline={includeTimeline}" + }; + return await requester.GetAsync(url, region, arguments); } public long GetTournamentMatchId(Region region, string tournamentCode) { - var json = - requester.CreateGetRequest( - string.Format(MatchRootUrl, region) + string.Format(GetMatchIdUrl, tournamentCode), region); - - var matchIds = JsonConvert.DeserializeObject>(json); - - return matchIds.FirstOrDefault(); + var url = string.Format(MatchRootUrl, region) + string.Format(GetMatchIdUrl, tournamentCode); + return requester.Get>(url, region).FirstOrDefault(); } public async Task GetTournamentMatchIdAsync(Region region, string tournamentCode) { - var json = - await - requester.CreateGetRequestAsync( - string.Format(MatchRootUrl, region) + string.Format(GetMatchIdUrl, tournamentCode), region); - - return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject>(json).FirstOrDefault()); + var url = string.Format(MatchRootUrl, region) + string.Format(GetMatchIdUrl, tournamentCode); + return (await requester.GetAsync>(url, region)).FirstOrDefault(); } #endregion @@ -359,10 +315,7 @@ public async Task GetTournamentMatchIdAsync(Region region, string tourname #region Private Helpers private void SetTournamentRootUrl(bool useStub) { - if (useStub) - tournamentRootUrl = TournamentStubUrl; - else - tournamentRootUrl = TournamentUrl; + tournamentRootUrl = useStub ? TournamentStubUrl : TournamentUrl; } private Dictionary BuildTournamentUpdateBody(List allowedSummonerIds,