From 17ac4a4f354b89fa08e7031a7bd1c8baa3d0bdd7 Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Wed, 4 May 2016 23:25:59 +0900 Subject: [PATCH] =?utf8?q?HttpTwitter.RateLimitStatus=E3=83=A1=E3=82=BD?= =?utf8?q?=E3=83=83=E3=83=89=E3=82=92TwitterApi=E3=82=AF=E3=83=A9=E3=82=B9?= =?utf8?q?=E3=81=AB=E7=BD=AE=E3=81=8D=E6=8F=9B=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- OpenTween.Tests/Api/TwitterApiStatusTest.cs | 20 +-------- OpenTween.Tests/Api/TwitterApiTest.cs | 23 ++++++++++ OpenTween/Api/DataModel/TwitterRateLimits.cs | 66 ++++++++++++++++++++++++++++ OpenTween/Api/TwitterApi.cs | 7 +++ OpenTween/Api/TwitterApiStatus.cs | 32 ++++++-------- OpenTween/Connection/HttpTwitter.cs | 10 ----- OpenTween/MyCommon.cs | 6 ++- OpenTween/OpenTween.csproj | 1 + OpenTween/Tween.cs | 2 +- OpenTween/Twitter.cs | 29 +++--------- 10 files changed, 123 insertions(+), 73 deletions(-) create mode 100644 OpenTween/Api/DataModel/TwitterRateLimits.cs diff --git a/OpenTween.Tests/Api/TwitterApiStatusTest.cs b/OpenTween.Tests/Api/TwitterApiStatusTest.cs index 394a6041..7ff71d2a 100644 --- a/OpenTween.Tests/Api/TwitterApiStatusTest.cs +++ b/OpenTween.Tests/Api/TwitterApiStatusTest.cs @@ -243,7 +243,6 @@ namespace OpenTween.Api Assert.True(eventCalled); } - [Fact(Skip = "Mono環境でエラーが発生する")] public void UpdateFromJsonTest() { var status = new TwitterApiStatus(); @@ -252,7 +251,7 @@ namespace OpenTween.Api status.AccessLimitUpdated += (s, e) => eventCalled = true; var json = "{\"resources\":{\"statuses\":{\"/statuses/home_timeline\":{\"limit\":150,\"remaining\":100,\"reset\":1356998400}}}}"; - status.UpdateFromJson(json); + status.UpdateFromJson(TwitterRateLimits.ParseJson(json)); var rateLimit = status.AccessLimit["/statuses/home_timeline"]; Assert.Equal(150, rateLimit.AccessLimitCount); @@ -263,23 +262,6 @@ namespace OpenTween.Api } [Fact] - public void UpdateFromJsonTest2() - { - var status = new TwitterApiStatus(); - - var eventCalled = false; - status.AccessLimitUpdated += (s, e) => eventCalled = true; - - var json = "INVALID JSON"; - Assert.Throws(() => status.UpdateFromJson(json)); - - var rateLimit = status.AccessLimit["/statuses/home_timeline"]; - Assert.Null(rateLimit); - - Assert.False(eventCalled); - } - - [Fact] public void AccessLimitUpdatedTest() { var apiStatus = new TwitterApiStatus(); diff --git a/OpenTween.Tests/Api/TwitterApiTest.cs b/OpenTween.Tests/Api/TwitterApiTest.cs index db7a11d0..273ff89f 100644 --- a/OpenTween.Tests/Api/TwitterApiTest.cs +++ b/OpenTween.Tests/Api/TwitterApiTest.cs @@ -783,6 +783,29 @@ namespace OpenTween.Api } [Fact] + public async Task ApplicationRateLimitStatus_Test() + { + using (var twitterApi = new TwitterApi()) + { + var mock = new Mock(); + mock.Setup(x => + x.GetAsync( + new Uri("application/rate_limit_status.json", UriKind.Relative), + null, + "/application/rate_limit_status") + ) + .ReturnsAsync(new TwitterRateLimits()); + + twitterApi.apiConnection = mock.Object; + + await twitterApi.ApplicationRateLimitStatus() + .ConfigureAwait(false); + + mock.VerifyAll(); + } + } + + [Fact] public async Task Configuration_Test() { using (var twitterApi = new TwitterApi()) diff --git a/OpenTween/Api/DataModel/TwitterRateLimits.cs b/OpenTween/Api/DataModel/TwitterRateLimits.cs new file mode 100644 index 00000000..5a3538f6 --- /dev/null +++ b/OpenTween/Api/DataModel/TwitterRateLimits.cs @@ -0,0 +1,66 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2016 kim_upsilon (@kim_upsilon) +// All rights reserved. +// +// This file is part of OpenTween. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. If not, see , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace OpenTween.Api.DataModel +{ + [DataContract] + public class TwitterRateLimits + { + [DataMember(Name = "rate_limit_context")] + public TwitterRateLimitContext RateLimitContext { get; set; } + + [DataContract] + public class TwitterRateLimitContext + { + [DataMember(Name = "access_token")] + public string AccessToken { get; set; } + } + + [DataMember(Name = "resources")] + public IDictionary> Resources { get; set; } + + [DataContract] + public class TwitterRateLimit + { + [DataMember(Name = "limit")] + public int Limit { get; set; } + + [DataMember(Name = "remaining")] + public int Remaining { get; set; } + + [DataMember(Name = "reset")] + public long Reset { get; set; } + } + + /// + public static TwitterRateLimits ParseJson(string json) + { + return MyCommon.CreateDataFromJson(json); + } + } +} diff --git a/OpenTween/Api/TwitterApi.cs b/OpenTween/Api/TwitterApi.cs index a5c134d3..52f75727 100644 --- a/OpenTween/Api/TwitterApi.cs +++ b/OpenTween/Api/TwitterApi.cs @@ -434,6 +434,13 @@ namespace OpenTween.Api return this.apiConnection.PostLazyAsync(endpoint, param, paramMedia); } + public Task ApplicationRateLimitStatus() + { + var endpoint = new Uri("application/rate_limit_status.json", UriKind.Relative); + + return this.apiConnection.GetAsync(endpoint, null, "/application/rate_limit_status"); + } + public Task Configuration() { var endpoint = new Uri("help/configuration.json", UriKind.Relative); diff --git a/OpenTween/Api/TwitterApiStatus.cs b/OpenTween/Api/TwitterApiStatus.cs index 6190e829..12e40e49 100644 --- a/OpenTween/Api/TwitterApiStatus.cs +++ b/OpenTween/Api/TwitterApiStatus.cs @@ -136,25 +136,21 @@ namespace OpenTween.Api private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - public void UpdateFromJson(string json) + public void UpdateFromJson(TwitterRateLimits json) { - using (var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(json), XmlDictionaryReaderQuotas.Max)) - { - var xElm = XElement.Load(jsonReader); - XNamespace a = "item"; - - var q = - from res in xElm.Element("resources").Descendants(a + "item") // a:item 要素を列挙 - select new { - endpointName = res.Attribute("item").Value, - limit = new ApiLimit( - int.Parse(res.Element("limit").Value), - int.Parse(res.Element("remaining").Value), - UnixEpoch.AddSeconds(long.Parse(res.Element("reset").Value)).ToLocalTime() - ), - }; - this.AccessLimit.AddAll(q.ToDictionary(x => x.endpointName, x => x.limit)); - } + var rateLimits = + from res in json.Resources + from item in res.Value + select new { + endpointName = item.Key, + limit = new ApiLimit( + item.Value.Limit, + item.Value.Remaining, + UnixEpoch.AddSeconds(item.Value.Reset).ToLocalTime() + ), + }; + + this.AccessLimit.AddAll(rateLimits.ToDictionary(x => x.endpointName, x => x.limit)); } protected virtual void OnAccessLimitUpdated(AccessLimitUpdatedEventArgs e) diff --git a/OpenTween/Connection/HttpTwitter.cs b/OpenTween/Connection/HttpTwitter.cs index a4c07755..fc7b8756 100644 --- a/OpenTween/Connection/HttpTwitter.cs +++ b/OpenTween/Connection/HttpTwitter.cs @@ -200,16 +200,6 @@ namespace OpenTween this.CreateApiCalllback("/saved_searches/list")); } - public HttpStatusCode RateLimitStatus(ref string content) - { - return httpCon.GetContent(GetMethod, - this.CreateTwitterUri("/1.1/application/rate_limit_status.json"), - null, - ref content, - this.CreateRatelimitHeadersDict(), - this.CreateApiCalllback("/application/rate_limit_status")); - } - #region Lists public HttpStatusCode GetLists(string user, ref string content) { diff --git a/OpenTween/MyCommon.cs b/OpenTween/MyCommon.cs index fb6631c4..c48f222d 100644 --- a/OpenTween/MyCommon.cs +++ b/OpenTween/MyCommon.cs @@ -843,7 +843,11 @@ namespace OpenTween var buf = Encoding.Unicode.GetBytes(content); using (var stream = new MemoryStream(buf)) { - data = (T)((new DataContractJsonSerializer(typeof(T))).ReadObject(stream)); + var settings = new DataContractJsonSerializerSettings + { + UseSimpleDictionaryFormat = true, + }; + data = (T)((new DataContractJsonSerializer(typeof(T), settings)).ReadObject(stream)); } return data; } diff --git a/OpenTween/OpenTween.csproj b/OpenTween/OpenTween.csproj index 8fd4f0d4..244f7b63 100644 --- a/OpenTween/OpenTween.csproj +++ b/OpenTween/OpenTween.csproj @@ -79,6 +79,7 @@ Code + diff --git a/OpenTween/Tween.cs b/OpenTween/Tween.cs index 1b489d31..54adcba9 100644 --- a/OpenTween/Tween.cs +++ b/OpenTween/Tween.cs @@ -11332,7 +11332,7 @@ namespace OpenTween try { - var task = Task.Run(() => this.tw.GetInfoApi()); + var task = this.tw.GetInfoApi(); apiStatus = await dialog.WaitForAsync(this, task); } catch (WebApiException) diff --git a/OpenTween/Twitter.cs b/OpenTween/Twitter.cs index 81647248..9e65c0d1 100644 --- a/OpenTween/Twitter.cs +++ b/OpenTween/Twitter.cs @@ -2061,37 +2061,18 @@ namespace OpenTween return Tuple.Create(sourceText, sourceUri); } - public TwitterApiStatus GetInfoApi() + public async Task GetInfoApi() { if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return null; if (MyCommon._endingFlag) return null; - HttpStatusCode res; - var content = ""; - try - { - res = twCon.RateLimitStatus(ref content); - } - catch (Exception) - { - this.ResetApiStatus(); - return null; - } + var limits = await this.Api.ApplicationRateLimitStatus() + .ConfigureAwait(false); - this.CheckStatusCode(res, content); + MyCommon.TwitterApiInfo.UpdateFromJson(limits); - try - { - MyCommon.TwitterApiInfo.UpdateFromJson(content); - return MyCommon.TwitterApiInfo; - } - catch (Exception ex) - { - MyCommon.TraceOut(ex, MethodBase.GetCurrentMethod().Name + " " + content); - MyCommon.TwitterApiInfo.Reset(); - return null; - } + return MyCommon.TwitterApiInfo; } /// -- 2.11.0