Assert.True(eventCalled);
}
- [Fact(Skip = "Mono環境でエラーが発生する")]
public void UpdateFromJsonTest()
{
var status = new TwitterApiStatus();
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);
}
[Fact]
- public void UpdateFromJsonTest2()
- {
- var status = new TwitterApiStatus();
-
- var eventCalled = false;
- status.AccessLimitUpdated += (s, e) => eventCalled = true;
-
- var json = "INVALID JSON";
- Assert.Throws<XmlException>(() => status.UpdateFromJson(json));
-
- var rateLimit = status.AccessLimit["/statuses/home_timeline"];
- Assert.Null(rateLimit);
-
- Assert.False(eventCalled);
- }
-
- [Fact]
public void AccessLimitUpdatedTest()
{
var apiStatus = new TwitterApiStatus();
}
[Fact]
+ public async Task ApplicationRateLimitStatus_Test()
+ {
+ using (var twitterApi = new TwitterApi())
+ {
+ var mock = new Mock<IApiConnection>();
+ mock.Setup(x =>
+ x.GetAsync<TwitterRateLimits>(
+ 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())
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2016 kim_upsilon (@kim_upsilon) <https://upsilo.net/~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 <http://www.gnu.org/licenses/>, 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<string, IDictionary<string, TwitterRateLimit>> 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; }
+ }
+
+ /// <exception cref="SerializationException"/>
+ public static TwitterRateLimits ParseJson(string json)
+ {
+ return MyCommon.CreateDataFromJson<TwitterRateLimits>(json);
+ }
+ }
+}
return this.apiConnection.PostLazyAsync<TwitterUser>(endpoint, param, paramMedia);
}
+ public Task<TwitterRateLimits> ApplicationRateLimitStatus()
+ {
+ var endpoint = new Uri("application/rate_limit_status.json", UriKind.Relative);
+
+ return this.apiConnection.GetAsync<TwitterRateLimits>(endpoint, null, "/application/rate_limit_status");
+ }
+
public Task<TwitterConfiguration> Configuration()
{
var endpoint = new Uri("help/configuration.json", UriKind.Relative);
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)
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)
{
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;
}
<SubType>Code</SubType>
</Compile>
<Compile Include="Api\DataModel\TwitterPlace.cs" />
+ <Compile Include="Api\DataModel\TwitterRateLimits.cs" />
<Compile Include="Api\DataModel\TwitterSearchResult.cs" />
<Compile Include="Api\DataModel\TwitterStatus.cs" />
<Compile Include="Api\DataModel\TwitterStreamEvent.cs" />
try
{
- var task = Task.Run(() => this.tw.GetInfoApi());
+ var task = this.tw.GetInfoApi();
apiStatus = await dialog.WaitForAsync(this, task);
}
catch (WebApiException)
return Tuple.Create(sourceText, sourceUri);
}
- public TwitterApiStatus GetInfoApi()
+ public async Task<TwitterApiStatus> 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;
}
/// <summary>