diff --git a/PocketSharp.Tests/GetTests.cs b/PocketSharp.Tests/GetTests.cs index 42f4b92..54b4367 100644 --- a/PocketSharp.Tests/GetTests.cs +++ b/PocketSharp.Tests/GetTests.cs @@ -151,5 +151,14 @@ namespace PocketSharp.Tests Assert.True(statistics.CountAll > 0); } + + + [Fact] + public async Task AreLimitsRetrieved() + { + PocketLimits limits = await client.GetUsageLimits(); + + Assert.True(limits.RateLimitForConsumerKey > 9999); + } } } diff --git a/PocketSharp/Components/Statistics.cs b/PocketSharp/Components/Statistics.cs index 24fdec5..7a482e1 100644 --- a/PocketSharp/Components/Statistics.cs +++ b/PocketSharp/Components/Statistics.cs @@ -1,4 +1,5 @@ -using PocketSharp.Models; +using Newtonsoft.Json; +using PocketSharp.Models; using System; using System.Threading.Tasks; @@ -14,9 +15,50 @@ namespace PocketSharp /// /// /// - public async Task Statistics() + public async Task GetUserStatistics() { return await Request("stats"); } + + + /// + /// Statistics from the user account. + /// + /// + /// + [Obsolete("Please use GetUserStatistics")] + public async Task Statistics() + { + return await GetUserStatistics(); + } + + + /// + /// Returns API usage statistics. + /// If a request was made before, the data is returned synchronously from the cache. + /// Note: This method only works for authenticated users with a given AccessCode. + /// + /// + /// + public async Task GetUsageLimits() + { + string rateLimitForConsumerKey = TryGetHeaderValue(lastHeaders, "X-Limit-Key-Limit"); + + if (rateLimitForConsumerKey == null) + { + // this is the fastest way to do a non-failing request to receive the correct headers + await Get(count: 1); + } + + return new PocketLimits() + { + RateLimitForConsumerKey = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-Key-Limit")), + RemainingCallsForConsumerKey = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-Key-Remaining")), + SecondsUntilLimitResetsForConsumerKey = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-Key-Reset")), + RateLimitForUser = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-User-Limit")), + RemainingCallsForUser = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-User-Remaining")), + SecondsUntilLimitResetsForUser = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-User-Reset")) + }; + } } } diff --git a/PocketSharp/Models/PocketLimits.cs b/PocketSharp/Models/PocketLimits.cs new file mode 100644 index 0000000..3725eef --- /dev/null +++ b/PocketSharp/Models/PocketLimits.cs @@ -0,0 +1,67 @@ +using Newtonsoft.Json; +using PropertyChanged; + +namespace PocketSharp.Models +{ + /// + /// API Limitation Statistics + /// + [JsonObject] + [ImplementPropertyChanged] + public class PocketLimits + { + /// + /// Gets or sets the rate limit. + /// + /// + /// Rate limit for current consumer key. + /// + [JsonProperty("X-Limit-Key-Limit")] + public int RateLimitForConsumerKey { get; set; } + + /// + /// Gets or sets the remaining calls. + /// + /// + /// Remaining calls for current consumer key. + /// + [JsonProperty("X-Limit-Key-Remaining")] + public int RemainingCallsForConsumerKey { get; set; } + + /// + /// Gets or sets the reset seconds. + /// + /// + /// Seconds until limit resets for current consumer key. + /// + [JsonProperty("X-Limit-Key-Reset")] + public int SecondsUntilLimitResetsForConsumerKey { get; set; } + + /// + /// Gets or sets the rate limit. + /// + /// + /// Rate limit for current user. + /// + [JsonProperty("X-Limit-User-Limit")] + public int RateLimitForUser { get; set; } + + /// + /// Gets or sets the remaining calls. + /// + /// + /// Remaining calls for current user. + /// + [JsonProperty("X-Limit-User-Remaining")] + public int RemainingCallsForUser { get; set; } + + /// + /// Gets or sets the reset seconds. + /// + /// + /// Seconds until limit resets for current user. + /// + [JsonProperty("X-Limit-User-Reset")] + public int SecondsUntilLimitResetsForUser { get; set; } + } +} diff --git a/PocketSharp/PocketClient.cs b/PocketSharp/PocketClient.cs index 14291cd..e8df705 100644 --- a/PocketSharp/PocketClient.cs +++ b/PocketSharp/PocketClient.cs @@ -22,6 +22,11 @@ namespace PocketSharp /// protected readonly HttpClient _restClient; + /// + /// Caches HTTP headers from last response + /// + private HttpResponseHeaders lastHeaders; + /// /// The base URL for the Pocket API /// @@ -54,6 +59,7 @@ namespace PocketSharp public string AccessCode { get; set; } + /// /// Initializes a new instance of the class. /// @@ -144,6 +150,9 @@ namespace PocketSharp // validate HTTP response ValidateResponse(response); + // cache headers + lastHeaders = response.Headers; + // read response var responseString = await response.Content.ReadAsStringAsync(); @@ -267,6 +276,11 @@ namespace PocketSharp { string result = null; + if (headers == null || String.IsNullOrEmpty(key)) + { + return null; + } + foreach (var header in headers) { if (header.Key == key) @@ -275,6 +289,7 @@ namespace PocketSharp headerEnumerator.MoveNext(); result = headerEnumerator.Current; + break; } } diff --git a/PocketSharp/PocketSharp.csproj b/PocketSharp/PocketSharp.csproj index ab804b0..7371795 100644 --- a/PocketSharp/PocketSharp.csproj +++ b/PocketSharp/PocketSharp.csproj @@ -44,6 +44,7 @@ +