--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2013 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.Text;
+using NUnit.Framework;
+
+namespace OpenTween.Api
+{
+ [TestFixture]
+ class ApiLimitTest
+ {
+ public static object[] Equals_TestCase =
+ {
+ new object[] { new ApiLimit(150, 100, new DateTime(2013, 1, 1, 0, 0, 0)), true },
+ new object[] { new ApiLimit(350, 100, new DateTime(2013, 1, 1, 0, 0, 0)), false },
+ new object[] { new ApiLimit(150, 150, new DateTime(2013, 1, 1, 0, 0, 0)), false },
+ new object[] { new ApiLimit(150, 100, new DateTime(2012, 12, 31, 0, 0, 0)), false },
+ new object[] { null, false },
+ new object[] { new object(), false },
+ };
+ [TestCaseSource("Equals_TestCase")]
+ public void EqualsTest(object obj2, bool expect)
+ {
+ var obj1 = new ApiLimit(150, 100, new DateTime(2013, 1, 1, 0, 0, 0));
+
+ Assert.That(obj1.Equals(obj2), Is.EqualTo(expect));
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2013 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.Text;
+using NUnit.Framework;
+
+namespace OpenTween.Api
+{
+ [TestFixture]
+ class TwitterApiStatusTest
+ {
+ [Test]
+ public void ResetTest()
+ {
+ var apiStatus = new TwitterApiStatus();
+
+ apiStatus.AccessLimit = new ApiLimit(150, 100, new DateTime(2013, 1, 1, 0, 0, 0));
+ apiStatus.MediaUploadLimit = new ApiLimit(150, 100, new DateTime(2013, 1, 1, 0, 0, 0));
+ apiStatus.AccessLevel = TwitterApiAccessLevel.ReadWriteAndDirectMessage;
+
+ apiStatus.Reset();
+
+ Assert.That(apiStatus.AccessLimit, Is.Null);
+ Assert.That(apiStatus.MediaUploadLimit, Is.Null);
+ Assert.That(apiStatus.AccessLevel, Is.EqualTo(TwitterApiAccessLevel.Anonymous));
+ }
+
+ public static object[] ParseRateLimit_TestCase =
+ {
+ new object[] {
+ new Dictionary<string, string> {
+ {"X-RateLimit-Limit", "150"},
+ {"X-RateLimit-Remaining", "100"},
+ {"X-RateLimit-Reset", "1356998400"},
+ },
+ new ApiLimit(150, 100, new DateTime(2013, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime()),
+ },
+ new object[] {
+ new Dictionary<string, string> {
+ {"X-RateLimit-Limit", "150"},
+ {"X-RateLimit-Remaining", "100"},
+ {"X-RateLimit-Reset", "hogehoge"},
+ },
+ null,
+ },
+ new object[] {
+ new Dictionary<string, string> {
+ {"X-RateLimit-Limit", "150"},
+ {"X-RateLimit-Remaining", "100"},
+ },
+ null,
+ },
+ };
+ [TestCaseSource("ParseRateLimit_TestCase")]
+ public void ParseRateLimitTest(IDictionary<string, string> header, ApiLimit expect)
+ {
+ var limit = TwitterApiStatus.ParseRateLimit(header);
+ Assert.That(limit, Is.EqualTo(expect));
+ }
+
+ public static object[] ParseMediaRateLimit_TestCase =
+ {
+ new object[] {
+ new Dictionary<string, string> {
+ {"X-MediaRateLimit-Limit", "30"},
+ {"X-MediaRateLimit-Remaining", "20"},
+ {"X-MediaRateLimit-Reset", "1234567890"},
+ },
+ new ApiLimit(30, 20, new DateTime(2009, 2, 13, 23, 31, 30, DateTimeKind.Utc).ToLocalTime()),
+ },
+ new object[] {
+ new Dictionary<string, string> {
+ {"X-MediaRateLimit-Limit", "30"},
+ {"X-MediaRateLimit-Remaining", "20"},
+ {"X-MediaRateLimit-Reset", "hogehoge"},
+ },
+ null,
+ },
+ new object[] {
+ new Dictionary<string, string> {
+ {"X-MediaRateLimit-Limit", "30"},
+ {"X-MediaRateLimit-Remaining", "20"},
+ },
+ null,
+ },
+ };
+ [TestCaseSource("ParseMediaRateLimit_TestCase")]
+ public void ParseMediaRateLimitTest(IDictionary<string, string> header, ApiLimit expect)
+ {
+ var limit = TwitterApiStatus.ParseMediaRateLimit(header);
+ Assert.That(limit, Is.EqualTo(expect));
+ }
+
+ public static object[] ParseAccessLevel_TestCase =
+ {
+ new object[] {
+ new Dictionary<string, string> { {"X-Access-Level", "read"} },
+ TwitterApiAccessLevel.Read,
+ },
+ new object[] {
+ new Dictionary<string, string> { {"X-Access-Level", "read-write"} },
+ TwitterApiAccessLevel.ReadWrite,
+ },
+ new object[] {
+ new Dictionary<string, string> { {"X-Access-Level", "read-write-directmessages"} },
+ TwitterApiAccessLevel.ReadWriteAndDirectMessage,
+ },
+ new object[] {
+ new Dictionary<string, string> { {"X-Access-Level", ""} }, // 何故かたまに出てくるやつ
+ null,
+ },
+ new object[] {
+ new Dictionary<string, string> { },
+ null,
+ },
+ };
+ [TestCaseSource("ParseAccessLevel_TestCase")]
+ public void ParseAccessLevelTest(IDictionary<string, string> header, TwitterApiAccessLevel? expect)
+ {
+ var accessLevel = TwitterApiStatus.ParseAccessLevel(header);
+ Assert.That(accessLevel, Is.EqualTo(expect));
+ }
+
+ [Test]
+ public void UpdateFromHeaderTest()
+ {
+ var status = new TwitterApiStatus();
+
+ var eventCalled = false;
+ status.AccessLimitUpdated += (s, e) => eventCalled = true;
+
+ var header = new Dictionary<string, string>
+ {
+ {"X-RateLimit-Limit", "150"},
+ {"X-RateLimit-Remaining", "100"},
+ {"X-RateLimit-Reset", "1356998400"},
+ {"X-MediaRateLimit-Limit", "30"},
+ {"X-MediaRateLimit-Remaining", "20"},
+ {"X-MediaRateLimit-Reset", "1357084800"},
+ {"X-Access-Level", "read-write-directmessages"},
+ };
+
+ status.UpdateFromHeader(header);
+
+ var rateLimit = status.AccessLimit;
+ Assert.That(rateLimit.AccessLimitCount, Is.EqualTo(150));
+ Assert.That(rateLimit.AccessLimitRemain, Is.EqualTo(100));
+ Assert.That(rateLimit.AccessLimitResetDate, Is.EqualTo(new DateTime(2013, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime()));
+
+ var mediaLimit = status.MediaUploadLimit;
+ Assert.That(mediaLimit.AccessLimitCount, Is.EqualTo(30));
+ Assert.That(mediaLimit.AccessLimitRemain, Is.EqualTo(20));
+ Assert.That(mediaLimit.AccessLimitResetDate, Is.EqualTo(new DateTime(2013, 1, 2, 0, 0, 0, DateTimeKind.Utc).ToLocalTime()));
+
+ Assert.That(status.AccessLevel, Is.EqualTo(TwitterApiAccessLevel.ReadWriteAndDirectMessage));
+
+ Assert.That(eventCalled, Is.True);
+ }
+
+ [Test]
+ public void UpdateFromApiTest()
+ {
+ var status = new TwitterApiStatus();
+
+ var eventCalled = false;
+ status.AccessLimitUpdated += (s, e) => eventCalled = true;
+
+ var apiResponse = new TwitterDataModel.RateLimitStatus
+ {
+ HourlyLimit = 150,
+ RemainingHits = 100,
+ ResetTime = "Tue Jan 01 00:00:00 +0000 2013",
+ ResetTimeInSeconds = 1356998400,
+ Photos = new TwitterDataModel.MediaRateLimitStatus
+ {
+ DailyLimit = 30,
+ RemainingHits = 20,
+ ResetTime = "Wed Jan 02 00:00:00 +0000 2013",
+ RestTimeInSeconds = 1357084800,
+ },
+ };
+
+ status.UpdateFromApi(apiResponse);
+
+ var rateLimit = status.AccessLimit;
+ Assert.That(rateLimit.AccessLimitCount, Is.EqualTo(150));
+ Assert.That(rateLimit.AccessLimitRemain, Is.EqualTo(100));
+ Assert.That(rateLimit.AccessLimitResetDate, Is.EqualTo(new DateTime(2013, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime()));
+
+ var mediaLimit = status.MediaUploadLimit;
+ Assert.That(mediaLimit.AccessLimitCount, Is.EqualTo(30));
+ Assert.That(mediaLimit.AccessLimitRemain, Is.EqualTo(20));
+ Assert.That(mediaLimit.AccessLimitResetDate, Is.EqualTo(new DateTime(2013, 1, 2, 0, 0, 0, DateTimeKind.Utc).ToLocalTime()));
+
+ Assert.That(eventCalled, Is.True);
+ }
+
+ [Test]
+ public void UpdateFromApiTest2()
+ {
+ var status = new TwitterApiStatus();
+
+ var eventCalled = false;
+ status.AccessLimitUpdated += (s, e) => eventCalled = true;
+
+ var apiResponse = new TwitterDataModel.RateLimitStatus
+ {
+ HourlyLimit = 150,
+ RemainingHits = 100,
+ ResetTime = "Tue Jan 01 00:00:00 +0000 2013",
+ ResetTimeInSeconds = 1356998400,
+ Photos = null,
+ };
+
+ status.UpdateFromApi(apiResponse);
+
+ var rateLimit = status.AccessLimit;
+ Assert.That(rateLimit.AccessLimitCount, Is.EqualTo(150));
+ Assert.That(rateLimit.AccessLimitRemain, Is.EqualTo(100));
+ Assert.That(rateLimit.AccessLimitResetDate, Is.EqualTo(new DateTime(2013, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime()));
+
+ Assert.That(status.MediaUploadLimit, Is.Null);
+
+ Assert.That(eventCalled, Is.True);
+ }
+
+ [Test]
+ public void UpdateFromApiTest3()
+ {
+ var status = new TwitterApiStatus();
+
+ var eventCalled = false;
+ status.AccessLimitUpdated += (s, e) => eventCalled = true;
+
+ Assert.That(() => status.UpdateFromApi(null), Throws.TypeOf<ArgumentNullException>());
+
+ Assert.That(status.AccessLimit, Is.Null);
+ Assert.That(status.MediaUploadLimit, Is.Null);
+
+ Assert.That(eventCalled, Is.False);
+ }
+
+ [Test]
+ public void AccessLimitUpdatedTest()
+ {
+ var apiStatus = new TwitterApiStatus();
+
+ var eventCount = 0;
+ apiStatus.AccessLimitUpdated += (s, e) => eventCount++;
+
+ Assert.That(eventCount, Is.EqualTo(0));
+
+ apiStatus.AccessLimit = new ApiLimit(150, 100, new DateTime(2013, 1, 1, 0, 0, 0));
+ Assert.That(eventCount, Is.EqualTo(1));
+
+ apiStatus.Reset();
+ Assert.That(eventCount, Is.EqualTo(2));
+ }
+ }
+}
+++ /dev/null
-// OpenTween - Client of Twitter
-// Copyright (c) 2012 the40san <http://sourceforge.jp/users/the40san/>
-// 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.Text;
-using System.Threading.Tasks;
-using NUnit.Framework;
-
-
-namespace OpenTween
-{
- [TestFixture]
- public class ApiInformationTest
- {
- [Test]
- public void Initialize()
- {
- ApiInformation apiinfo = new ApiInformation();
- apiinfo.Initialize();
-
- Assert.That(apiinfo.HttpHeaders["X-RateLimit-Remaining"], Is.EqualTo("-1"));
- Assert.That(apiinfo.HttpHeaders["X-RateLimit-Limit"], Is.EqualTo("-1"));
- Assert.That(apiinfo.HttpHeaders["X-RateLimit-Reset"], Is.EqualTo("-1"));
-
- Assert.That(apiinfo.HttpHeaders["X-Access-Level"], Is.EqualTo("read-write-directmessages"));
-
- Assert.That(apiinfo.HttpHeaders["X-MediaRateLimit-Remaining"], Is.EqualTo("-1"));
- Assert.That(apiinfo.HttpHeaders["X-MediaRateLimit-Limit"], Is.EqualTo("-1"));
- Assert.That(apiinfo.HttpHeaders["X-MediaRateLimit-Reset"], Is.EqualTo("-1"));
-
-
- }
-
- [Test]
- [Combinatorial]
- public void Test_MaxCount([Values(100, 0, -100)]int value)
- {
- ApiInformation apiinfo = new ApiInformation();
- apiinfo.MaxCount = value;
- Assert.That(apiinfo.MaxCount, Is.EqualTo(value));
- }
-
-
- [TestCase(-100, Result = -100)]
- [TestCase(0, Result = 0)]
- [TestCase(100, Result = 100)]
- [TestCase(int.MaxValue, Result = int.MaxValue)]
- [TestCase(int.MinValue, Result = int.MinValue)]
- public int Test_RemainCount(int value)
- {
- ApiInformation apiinfo = new ApiInformation();
- apiinfo.RemainCount = value;
- return apiinfo.RemainCount;
- }
-
-
-
-
-
- [TestCase(-100, Result = -100)]
- [TestCase(0, Result = 0)]
- [TestCase(100, Result = 100)]
- [TestCase(int.MaxValue, Result = int.MaxValue)]
- [TestCase(int.MinValue, Result = int.MinValue)]
- public int Test_MediaMaxCount(int value)
- {
- ApiInformation apiinfo = new ApiInformation();
- apiinfo.MediaMaxCount = value;
- return apiinfo.MediaMaxCount;
- }
-
- [TestCase(-100, Result = -100)]
- [TestCase(0, Result = 0)]
- [TestCase(100, Result = 100)]
- [TestCase(int.MaxValue, Result = int.MaxValue)]
- [TestCase(int.MinValue, Result = int.MinValue)]
- public int Test_ResetTimeInSeconds(int value)
- {
- ApiInformation apiinfo = new ApiInformation();
- apiinfo.ResetTimeInSeconds = value;
- return apiinfo.ResetTimeInSeconds;
- }
-
- [TestCase(-100, Result = -100)]
- [TestCase(0, Result = 0)]
- [TestCase(100, Result = 100)]
- [TestCase(int.MaxValue, Result = int.MaxValue)]
- [TestCase(int.MinValue, Result = int.MinValue)]
- public int Test_UsingCount(int value)
- {
- ApiInformation apiinfo = new ApiInformation();
- apiinfo.UsingCount = value;
- return apiinfo.UsingCount;
- }
-
- //↓以下DateTime系
-
- [Test]
- public void Test_ConvertResetTimeInSecondsToResetTime()
- {
- ApiInformation apiinfo = new ApiInformation();
- DateTime d = apiinfo.ConvertResetTimeInSecondsToResetTime(-1);
- Assert.That(d, Is.EqualTo(new DateTime()));
- }
-
- [Test]
- public void Test_MediaResetTime()
- {
- ApiInformation apiinfo = new ApiInformation();
- DateTime d = new DateTime(1970, 1, 1, 0, 0, 0);
- apiinfo.MediaResetTime = d;
- Assert.That(apiinfo.MediaResetTime, Is.EqualTo(d));
- }
-
-
- }
-}
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="ApiInformationTest.cs" />
+ <Compile Include="Api\ApiLimitTest.cs" />
+ <Compile Include="Api\TwitterApiStatusTest.cs" />
<Compile Include="BingTest.cs" />
<Compile Include="FoursquareTest.cs" />
<Compile Include="LRUCacheDictionaryTest.cs" />
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
- <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2013 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.Text;
+
+namespace OpenTween.Api
+{
+ public class ApiLimit
+ {
+ /// <summary>
+ /// API 実行回数制限の値
+ /// </summary>
+ public readonly int AccessLimitCount;
+
+ /// <summary>
+ /// API 実行回数制限までの残回数
+ /// </summary>
+ public readonly int AccessLimitRemain;
+
+ /// <summary>
+ /// API 実行回数制限がリセットされる日時
+ /// </summary>
+ public readonly DateTime AccessLimitResetDate;
+
+ public ApiLimit(int limitCount, int limitRemain, DateTime resetDate)
+ {
+ this.AccessLimitCount = limitCount;
+ this.AccessLimitRemain = limitRemain;
+ this.AccessLimitResetDate = resetDate;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return this.Equals(obj as ApiLimit);
+ }
+
+ public bool Equals(ApiLimit obj)
+ {
+ return obj != null &&
+ this.AccessLimitCount == obj.AccessLimitCount &&
+ this.AccessLimitRemain == obj.AccessLimitRemain &&
+ this.AccessLimitResetDate == obj.AccessLimitResetDate;
+ }
+
+ public override int GetHashCode()
+ {
+ return this.AccessLimitCount ^ this.AccessLimitRemain ^ this.AccessLimitResetDate.GetHashCode();
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2013 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.Text;
+
+namespace OpenTween.Api
+{
+ public enum TwitterApiAccessLevel
+ {
+ Anonymous,
+ Read,
+ ReadWrite,
+ ReadWriteAndDirectMessage,
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2013 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.Text;
+
+namespace OpenTween.Api
+{
+ public class TwitterApiStatus
+ {
+ public ApiLimit AccessLimit
+ {
+ get { return this._AccessLimit; }
+ set
+ {
+ this._AccessLimit = value;
+ this.OnAccessLimitUpdated(EventArgs.Empty);
+ }
+ }
+ public ApiLimit _AccessLimit;
+
+ public ApiLimit MediaUploadLimit { get; set; }
+ public TwitterApiAccessLevel AccessLevel { get; set; }
+
+ public event EventHandler AccessLimitUpdated;
+
+ private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+ protected internal TwitterApiStatus()
+ {
+ this.Reset();
+ }
+
+ public void Reset()
+ {
+ this.AccessLimit = null;
+ this.MediaUploadLimit = null;
+ this.AccessLevel = TwitterApiAccessLevel.Anonymous;
+ }
+
+ public void UpdateFromHeader(IDictionary<string, string> header)
+ {
+ var rateLimit = TwitterApiStatus.ParseRateLimit(header);
+ if (rateLimit != null)
+ this.AccessLimit = rateLimit;
+
+ var mediaLimit = TwitterApiStatus.ParseMediaRateLimit(header);
+ if (mediaLimit != null)
+ this.MediaUploadLimit = mediaLimit;
+
+ var accessLevel = TwitterApiStatus.ParseAccessLevel(header);
+ if (accessLevel.HasValue)
+ this.AccessLevel = accessLevel.Value;
+ }
+
+ internal static ApiLimit ParseRateLimit(IDictionary<string, string> header)
+ {
+ var limitCount = ParseHeaderValue(header, "X-RateLimit-Limit") ?? -1;
+ var limitRemain = ParseHeaderValue(header, "X-RateLimit-Remaining") ?? -1;
+ var limitReset = ParseHeaderValue(header, "X-RateLimit-Reset") ?? -1;
+
+ if (limitCount == -1 || limitRemain == -1 || limitReset == -1)
+ return null;
+
+ var limitResetDate = UnixEpoch.AddSeconds(limitReset).ToLocalTime();
+ return new ApiLimit(limitCount, limitRemain, limitResetDate);
+ }
+
+ internal static ApiLimit ParseMediaRateLimit(IDictionary<string, string> header)
+ {
+ var limitCount = ParseHeaderValue(header, "X-MediaRateLimit-Limit") ?? -1;
+ var limitRemain = ParseHeaderValue(header, "X-MediaRateLimit-Remaining") ?? -1;
+ var limitReset = ParseHeaderValue(header, "X-MediaRateLimit-Reset") ?? -1;
+
+ if (limitCount == -1 || limitRemain == -1 || limitReset == -1)
+ return null;
+
+ var limitResetDate = UnixEpoch.AddSeconds(limitReset).ToLocalTime();
+ return new ApiLimit(limitCount, limitRemain, limitResetDate);
+ }
+
+ internal static TwitterApiAccessLevel? ParseAccessLevel(IDictionary<string, string> header)
+ {
+ if (!header.ContainsKey("X-Access-Level"))
+ return null;
+
+ switch (header["X-Access-Level"])
+ {
+ case "read-write-directmessages":
+ case "read-write-privatemessages":
+ return TwitterApiAccessLevel.ReadWriteAndDirectMessage;
+ case "read-write":
+ return TwitterApiAccessLevel.ReadWrite;
+ case "read":
+ return TwitterApiAccessLevel.Read;
+ case "":
+ // たまに出てくる空文字列は無視する
+ return null;
+ default:
+ MyCommon.TraceOut("Unknown ApiAccessLevel:" + header["X-Access-Level"]);
+ return TwitterApiAccessLevel.ReadWriteAndDirectMessage;
+ }
+ }
+
+ internal static int? ParseHeaderValue(IDictionary<string, string> dict, params string[] keys)
+ {
+ foreach (var key in keys)
+ {
+ if (!dict.ContainsKey(key)) continue;
+
+ int result;
+ if (int.TryParse(dict[key], out result))
+ return result;
+ }
+
+ return null;
+ }
+
+ public void UpdateFromApi(TwitterDataModel.RateLimitStatus limit)
+ {
+ if (limit == null)
+ throw new ArgumentNullException();
+
+ this.AccessLimit = new ApiLimit(limit.HourlyLimit, limit.RemainingHits, MyCommon.DateTimeParse(limit.ResetTime));
+
+ var mediaLimit = limit.Photos;
+ if (mediaLimit != null)
+ {
+ this.MediaUploadLimit = new ApiLimit(mediaLimit.DailyLimit, mediaLimit.RemainingHits, MyCommon.DateTimeParse(mediaLimit.ResetTime));
+ }
+ }
+
+ protected virtual void OnAccessLimitUpdated(EventArgs e)
+ {
+ if (this.AccessLimitUpdated != null)
+ this.AccessLimitUpdated(this, e);
+ }
+ }
+}
+++ /dev/null
-// OpenTween - Client of Twitter
-// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
-// (c) 2008-2011 Moz (@syo68k)
-// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
-// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
-// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
-// (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
-// 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;
-
-namespace OpenTween
-{
- public class ApiInformationChangedEventArgs : EventArgs
- {
- public ApiInfo ApiInfo = new ApiInfo();
- }
-
- public abstract class ApiInfoBase
- {
- protected static int _MaxCount = -1;
- protected static int _RemainCount = -1;
- protected static DateTime _ResetTime = new DateTime();
- protected static int _ResetTimeInSeconds = -1;
- protected static int _UsingCount = -1;
- protected static ApiAccessLevel _AccessLevel = ApiAccessLevel.None;
- protected static int _MediaMaxCount = -1;
- protected static DateTime _MediaResetTime = new DateTime();
- protected static int _MediaRemainCount = -1;
- }
-
- public enum ApiAccessLevel
- {
- None,
- Unknown,
- Read,
- ReadWrite,
- ReadWriteAndDirectMessage,
- }
-
- public class ApiInfo : ApiInfoBase
- {
- public int MaxCount;
- public int RemainCount;
- public DateTime ResetTime;
- public int ResetTimeInSeconds;
- public int UsingCount;
- public ApiAccessLevel AccessLevel;
- public int MediaMaxCount;
- public int MediaRemainCount;
- public DateTime MediaResetTime;
-
- public ApiInfo()
- {
- this.MaxCount = _MaxCount;
- this.RemainCount = _RemainCount;
- this.ResetTime = _ResetTime;
- this.ResetTimeInSeconds = _ResetTimeInSeconds;
- this.UsingCount = _UsingCount;
- this.AccessLevel = _AccessLevel;
- this.MediaMaxCount = _MediaMaxCount;
- this.MediaRemainCount = _MediaRemainCount;
- this.MediaResetTime = _MediaResetTime;
- }
- }
-
- public class ApiInformation : ApiInfoBase
- {
- //private ReadOnly _lockobj As new Object 更新時にロックが必要かどうかは様子見
-
- public Dictionary<string, string> HttpHeaders = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
-
- public void Initialize()
- {
- HttpHeaders["X-RateLimit-Remaining"] = "-1";
- HttpHeaders["X-RateLimit-Limit"] = "-1";
- HttpHeaders["X-RateLimit-Reset"] = "-1";
- HttpHeaders["X-Access-Level"] = "read-write-directmessages";
- HttpHeaders["X-MediaRateLimit-Remaining"] = "-1";
- HttpHeaders["X-MediaRateLimit-Limit"] = "-1";
- HttpHeaders["X-MediaRateLimit-Reset"] = "-1";
-
- _MaxCount = -1;
- _RemainCount = -1;
- _ResetTime = new DateTime();
- _ResetTimeInSeconds = -1;
- AccessLevel = ApiAccessLevel.None;
- _MediaMaxCount = -1;
- _MediaRemainCount = -1;
- _MediaResetTime = new DateTime();
-
- //_UsingCount = -1
- var arg = new ApiInformationChangedEventArgs();
- var changed = Changed;
- if (changed != null)
- {
- changed(this, arg);
- }
- }
-
- public DateTime ConvertResetTimeInSecondsToResetTime(int seconds)
- {
- if (seconds >= 0)
- {
- return System.TimeZone.CurrentTimeZone.ToLocalTime((new DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(seconds));
- }
- else
- {
- return new DateTime();
- }
- }
-
- public event EventHandler<ApiInformationChangedEventArgs> Changed;
-
- private void Raise_Changed()
- {
- var arg = new ApiInformationChangedEventArgs();
- var changed = Changed;
- if (changed != null)
- {
- changed(this, arg);
- }
- _MaxCount = arg.ApiInfo.MaxCount;
- _RemainCount = arg.ApiInfo.RemainCount;
- _ResetTime = arg.ApiInfo.ResetTime;
- _ResetTimeInSeconds = arg.ApiInfo.ResetTimeInSeconds;
- //_UsingCount = arg.ApiInfo.UsingCount
- }
-
- public int MaxCount
- {
- get
- {
- return _MaxCount;
- }
- set
- {
- if (_MaxCount != value)
- {
- _MaxCount = value;
- Raise_Changed();
- }
- }
- }
-
- public int RemainCount
- {
- get
- {
- return _RemainCount;
- }
- set
- {
- if (_RemainCount != value)
- {
- _RemainCount = value;
- Raise_Changed();
- }
- }
- }
-
- public DateTime ResetTime
- {
- get
- {
- return _ResetTime;
- }
- set
- {
- if (_ResetTime != value)
- {
- _ResetTime = value;
- Raise_Changed();
- }
- }
- }
-
- public int MediaMaxCount
- {
- get
- {
- return _MediaMaxCount;
- }
- set
- {
- if (_MediaMaxCount != value)
- {
- _MediaMaxCount = value;
- Raise_Changed();
- }
- }
- }
-
- public int MediaRemainCount
- {
- get
- {
- return _MediaRemainCount;
- }
- set
- {
- if (_MediaRemainCount != value)
- {
- _MediaRemainCount = value;
- Raise_Changed();
- }
- }
- }
-
- public DateTime MediaResetTime
- {
- get
- {
- return _MediaResetTime;
- }
- set
- {
- if (_MediaResetTime != value)
- {
- _MediaResetTime = value;
- Raise_Changed();
- }
- }
- }
-
- public int ResetTimeInSeconds
- {
- get
- {
- return _ResetTimeInSeconds;
- }
- set
- {
- if (_ResetTimeInSeconds != value)
- {
- _ResetTimeInSeconds = value;
- Raise_Changed();
- }
- }
- }
-
- public int UsingCount
- {
- get
- {
- return _UsingCount;
- }
- set
- {
- if (_UsingCount != value)
- {
- _UsingCount = value;
- Raise_Changed();
- }
- }
- }
-
- public ApiAccessLevel AccessLevel
- {
- get
- {
- return _AccessLevel;
- }
- private set
- {
- if (_AccessLevel != value)
- {
- _AccessLevel = value;
- Raise_Changed();
- }
- }
- }
-
- public bool IsReadPermission
- {
- get
- {
- return AccessLevel == ApiAccessLevel.Read ||
- AccessLevel == ApiAccessLevel.ReadWrite ||
- AccessLevel == ApiAccessLevel.ReadWriteAndDirectMessage;
- }
- }
-
- public bool IsWritePermission
- {
- get
- {
- return AccessLevel == ApiAccessLevel.ReadWrite ||
- AccessLevel == ApiAccessLevel.ReadWriteAndDirectMessage;
- }
- }
-
- public bool IsDirectMessagePermission
- {
- get
- {
- return AccessLevel == ApiAccessLevel.ReadWriteAndDirectMessage;
- }
- }
-
- private int RemainCountFromHttpHeader
- {
- get
- {
- int result = 0;
- if (string.IsNullOrEmpty(HttpHeaders["X-RateLimit-Remaining"])) return -1;
- if (int.TryParse(HttpHeaders["X-RateLimit-Remaining"], out result))
- {
- return result;
- }
- return -1;
- }
- }
-
- private int MaxCountFromHttpHeader
- {
- get
- {
- int result;
- if (string.IsNullOrEmpty(HttpHeaders["X-RateLimit-Limit"])) return -1;
- if (int.TryParse(HttpHeaders["X-RateLimit-Limit"], out result))
- {
- return result;
- }
- return -1;
- }
- }
-
- private DateTime ResetTimeFromHttpHeader
- {
- get
- {
- int i;
- if (int.TryParse(HttpHeaders["X-RateLimit-Reset"], out i))
- {
- if (i >= 0)
- {
- return TimeZone.CurrentTimeZone.ToLocalTime((new DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(i));
- }
- else
- {
- return new DateTime();
- }
- }
- else
- {
- return new DateTime();
- }
- }
- }
-
- private int MediaRemainCountFromHttpHeader
- {
- get
- {
- int result = 0;
- if (string.IsNullOrEmpty(HttpHeaders["X-MediaRateLimit-Remaining"])) return -1;
- if (int.TryParse(HttpHeaders["X-MediaRateLimit-Remaining"], out result))
- {
- return result;
- }
- return -1;
- }
- }
-
- private int MediaMaxCountFromHttpHeader
- {
- get
- {
- int result = 0;
- if (string.IsNullOrEmpty(HttpHeaders["X-MediaRateLimit-Limit"])) return -1;
- if (int.TryParse(HttpHeaders["X-MediaRateLimit-Limit"], out result))
- {
- return result;
- }
- return -1;
- }
- }
-
- private DateTime MediaResetTimeFromHttpHeader
- {
- get
- {
- int i;
- if (int.TryParse(HttpHeaders["X-MediaRateLimit-Reset"], out i))
- {
- if (i >= 0)
- {
- return TimeZone.CurrentTimeZone.ToLocalTime((new DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(i));
- }
- else
- {
- return new DateTime();
- }
- }
- else
- {
- return new DateTime();
- }
- }
- }
-
- private ApiAccessLevel ApiAccessLevelFromHttpHeader
- {
- get
- {
- switch (HttpHeaders["X-Access-Level"])
- {
- case "read":
- return ApiAccessLevel.Read;
- case "read-write":
- return ApiAccessLevel.ReadWrite;
- case "read-write-directmessages":
- case "read-write-privatemessages":
- return ApiAccessLevel.ReadWriteAndDirectMessage;
- default:
- MyCommon.TraceOut("Unknown ApiAccessLevel:" + HttpHeaders["X-Access-Level"]);
- return ApiAccessLevel.ReadWriteAndDirectMessage; //未知のアクセスレベルの場合Read/Write/Dmと仮定して処理継続;
- }
- }
- }
-
- public void ParseHttpHeaders(Dictionary<string, string> headers)
- {
- int tmp;
- DateTime tmpd;
- tmp = MaxCountFromHttpHeader;
- if (tmp != -1)
- {
- _MaxCount = tmp;
- }
- tmp = RemainCountFromHttpHeader;
- if (tmp != -1)
- {
- _RemainCount = tmp;
- }
- tmpd = ResetTimeFromHttpHeader;
- if (tmpd != new DateTime())
- {
- _ResetTime = tmpd;
- }
-
- tmp = MediaMaxCountFromHttpHeader;
- if (tmp != -1)
- {
- _MediaMaxCount = tmp;
- }
- tmp = MediaRemainCountFromHttpHeader;
- if (tmp != -1)
- {
- _MediaRemainCount = tmp;
- }
- tmpd = MediaResetTimeFromHttpHeader;
- if (tmpd != new DateTime())
- {
- _MediaResetTime = tmpd;
- }
-
- AccessLevel = ApiAccessLevelFromHttpHeader;
- Raise_Changed();
- }
-
- public void WriteBackEventArgs(ApiInformationChangedEventArgs arg)
- {
- _MaxCount = arg.ApiInfo.MaxCount;
- _RemainCount = arg.ApiInfo.RemainCount;
- _ResetTime = arg.ApiInfo.ResetTime;
- _ResetTimeInSeconds = arg.ApiInfo.ResetTimeInSeconds;
- _UsingCount = arg.ApiInfo.UsingCount;
- Raise_Changed();
- }
- }
-}
using System.IO;
using System.Resources;
using OpenTween.Thumbnail;
+using System.Threading.Tasks;
namespace OpenTween
{
private void DisplayApiMaxCount()
{
- if (MyCommon.TwitterApiInfo.MaxCount > -1)
+ var limit = MyCommon.TwitterApiInfo.AccessLimit;
+ if (limit != null)
{
- LabelApiUsing.Text = string.Format(Properties.Resources.SettingAPIUse1, MyCommon.TwitterApiInfo.UsingCount, MyCommon.TwitterApiInfo.MaxCount);
+ LabelApiUsing.Text = string.Format(Properties.Resources.SettingAPIUse1, limit.AccessLimitCount - limit.AccessLimitRemain, limit.AccessLimitCount);
}
else
{
- LabelApiUsing.Text = string.Format(Properties.Resources.SettingAPIUse1, MyCommon.TwitterApiInfo.UsingCount, "???");
+ LabelApiUsing.Text = string.Format(Properties.Resources.SettingAPIUse1, "???", "???");
}
}
if (tw != null)
{
- if (MyCommon.TwitterApiInfo.MaxCount == -1)
+ var limit = MyCommon.TwitterApiInfo.AccessLimit;
+ if (limit == null)
{
if (Twitter.AccountState == MyCommon.ACCOUNT_STATE.Valid)
{
- MyCommon.TwitterApiInfo.UsingCount = UsingApi;
- Thread proc = new Thread(new System.Threading.ThreadStart(() => {
- tw.GetInfoApi(null); //取得エラー時はinfoCountは初期状態(値:-1)
- if (this.IsHandleCreated && !this.IsDisposed) Invoke(new MethodInvoker(DisplayApiMaxCount));
- }));
- proc.Start();
+ Task.Factory.StartNew(() => tw.GetInfoApi()) //取得エラー時はinfoCountは初期状態(値:-1)
+ .ContinueWith(t =>
+ {
+ if (this.IsHandleCreated && !this.IsDisposed)
+ {
+ this.DisplayApiMaxCount();
+ }
+ }, TaskScheduler.FromCurrentSynchronizationContext());
}
else
{
}
else
{
- LabelApiUsing.Text = string.Format(Properties.Resources.SettingAPIUse1, UsingApi, MyCommon.TwitterApiInfo.MaxCount);
+ LabelApiUsing.Text = string.Format(Properties.Resources.SettingAPIUse1, UsingApi, limit.AccessLimitCount);
}
}
private static string tks = "";
private static string un = "";
+ private Dictionary<string, string> apiStatusHeaders = new Dictionary<string, string>
+ {
+ {"X-Access-Level", ""},
+ {"X-RateLimit-Limit", ""},
+ {"X-RateLimit-Remaining", ""},
+ {"X-RateLimit-Reset", ""},
+ {"X-MediaRateLimit-Limit", ""},
+ {"X-MediaRateLimit-Remaining", ""},
+ {"X-MediaRateLimit-Reset", ""},
+ };
+
public void Initialize(string accessToken,
string accessTokenSecret,
string username,
param,
binary,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/users/show.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/friendships/show.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/statuses/show/" + id.ToString() + ".json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/statuses/home_timeline.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/statuses/user_timeline.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/statuses/public_timeline.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/statuses/mentions.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/direct_messages.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/direct_messages/sent.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/favorites.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/followers/ids.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/friendships/no_retweet_ids.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/account/rate_limit_status.json"),
null,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/lists.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/lists/subscriptions.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/lists/statuses.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/lists/members.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/lists/members/show.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
//return httpCon.GetContent(GetMethod,
// CreateTwitterUri("/1/" + user + "/" + list_id + "/members/" + id + ".json"),
CreateTwitterUri("/1/statuses/" + statusid.ToString()+ "/retweeted_by/ids.json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/related_results/show/" + id.ToString()+ ".json"),
param,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/blocks/blocking/ids.json"),
null,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/help/configuration.json"),
null,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
CreateTwitterUri("/1/account/verify_credentials.json"),
null,
ref content,
- MyCommon.TwitterApiInfo.HttpHeaders,
+ this.apiStatusHeaders,
GetApiCallback);
}
private void GetApiCallback(Object sender, ref HttpStatusCode code, ref string content)
{
if (code < HttpStatusCode.InternalServerError)
- MyCommon.TwitterApiInfo.ParseHttpHeaders(MyCommon.TwitterApiInfo.HttpHeaders);
+ MyCommon.TwitterApiInfo.UpdateFromHeader(this.apiStatusHeaders);
}
public HttpStatusCode UserStream(ref Stream content,
[DataContract]
public class RateLimitStatus
{
- [DataMember(Name = "reset_time_in_seconds")] public int RestTimeInSeconds;
+ [DataMember(Name = "reset_time_in_seconds")] public int ResetTimeInSeconds;
[DataMember(Name = "remaining_hits")] public int RemainingHits;
- [DataMember(Name = "reset_time")] public string RestTime;
+ [DataMember(Name = "reset_time")] public string ResetTime;
[DataMember(Name = "hourly_limit")] public int HourlyLimit;
+ [DataMember(Name = "photos")] public MediaRateLimitStatus Photos;
+ }
+
+ [DataContract]
+ public class MediaRateLimitStatus
+ {
+ [DataMember(Name = "reset_time_in_seconds")] public int RestTimeInSeconds;
+ [DataMember(Name = "remaining_hits")] public int RemainingHits;
+ [DataMember(Name = "reset_time")] public string ResetTime;
+ [DataMember(Name = "daily_limit")] public int DailyLimit;
}
[DataContract]
using System.Text.RegularExpressions;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
+using OpenTween.Api;
namespace OpenTween
{
return GetAssemblyName() + "/" + fileVersion;
}
- public static ApiInformation TwitterApiInfo = new ApiInformation();
+ public static TwitterApiStatus TwitterApiInfo = new TwitterApiStatus();
public static bool IsAnimatedGif(string filename)
{
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="ApiInformation.cs" />
+ <Compile Include="Api\ApiLimit.cs" />
+ <Compile Include="Api\TwitterApiAccessLevel.cs" />
+ <Compile Include="Api\TwitterApiStatus.cs" />
<Compile Include="ApplicationEvents.cs">
<SubType>Code</SubType>
</Compile>
using OpenTween.Thumbnail;
using System.Threading.Tasks;
using System.Net;
+using OpenTween.Api;
namespace OpenTween
{
SecurityManager = new InternetSecurityManager(PostBrowser);
- MyCommon.TwitterApiInfo.Changed += SetStatusLabelApiHandler;
+ MyCommon.TwitterApiInfo.AccessLimitUpdated += SetStatusLabelApiHandler;
Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
string[] cmdArgs = Environment.GetCommandLineArgs();
delegate void SetStatusLabelApiDelegate();
- private void SetStatusLabelApiHandler(object sender, ApiInformationChangedEventArgs e)
+ private void SetStatusLabelApiHandler(object sender, EventArgs e)
{
try
{
private void SetStatusLabelApi()
{
- this._apiGauge.RemainCount = MyCommon.TwitterApiInfo.RemainCount;
- this._apiGauge.MaxCount = MyCommon.TwitterApiInfo.MaxCount;
- this._apiGauge.ResetTime = MyCommon.TwitterApiInfo.ResetTime;
+ var apiLimit = MyCommon.TwitterApiInfo.AccessLimit;
+ if (apiLimit == null)
+ return;
+
+ this._apiGauge.RemainCount = apiLimit.AccessLimitRemain;
+ this._apiGauge.MaxCount = apiLimit.AccessLimitCount;
+ this._apiGauge.ResetTime = apiLimit.AccessLimitResetDate;
}
private void SetStatusLabelUrl()
GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
// 権限チェック read/write権限(xAuthで取得したトークン)の場合は再認証を促す
- if (MyCommon.TwitterApiInfo.AccessLevel == ApiAccessLevel.ReadWrite)
+ if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
{
MessageBox.Show(Properties.Resources.ReAuthorizeText);
SettingStripMenuItem_Click(null, null);
}
- private class GetApiInfoArgs
- {
- public Twitter tw;
- public ApiInfo info;
- }
-
private void GetApiInfo_Dowork(object sender, DoWorkEventArgs e)
{
- GetApiInfoArgs args = (GetApiInfoArgs)e.Argument;
- e.Result = tw.GetInfoApi(args.info);
+ if (tw.GetInfoApi())
+ e.Result = MyCommon.TwitterApiInfo;
+ else
+ e.Result = null;
}
private void ApiUsageInfoMenuItem_Click(object sender, EventArgs e)
{
- ApiInfo info = new ApiInfo();
StringBuilder tmp = new StringBuilder();
- GetApiInfoArgs args = new GetApiInfoArgs() {tw = tw, info = info};
- using (FormInfo dlg = new FormInfo(this, Properties.Resources.ApiInfo6, GetApiInfo_Dowork, null, args))
+ using (FormInfo dlg = new FormInfo(this, Properties.Resources.ApiInfo6, GetApiInfo_Dowork))
{
dlg.ShowDialog();
- if ((bool)dlg.Result)
+ TwitterApiStatus result = dlg.Result as TwitterApiStatus;
+ if (result != null)
{
- tmp.AppendLine(Properties.Resources.ApiInfo1 + args.info.MaxCount.ToString());
- tmp.AppendLine(Properties.Resources.ApiInfo2 + args.info.RemainCount.ToString());
- tmp.AppendLine(Properties.Resources.ApiInfo3 + args.info.ResetTime.ToString());
- tmp.AppendLine(Properties.Resources.ApiInfo7 + (tw.UserStreamEnabled ? Properties.Resources.Enable : Properties.Resources.Disable).ToString());
+ tmp.AppendLine(Properties.Resources.ApiInfo1 + result.AccessLimit.AccessLimitCount);
+ tmp.AppendLine(Properties.Resources.ApiInfo2 + result.AccessLimit.AccessLimitRemain);
+ tmp.AppendLine(Properties.Resources.ApiInfo3 + result.AccessLimit.AccessLimitResetDate);
+ tmp.AppendLine(Properties.Resources.ApiInfo7 + (tw.UserStreamEnabled ? Properties.Resources.Enable : Properties.Resources.Disable));
tmp.AppendLine();
- tmp.AppendLine(Properties.Resources.ApiInfo8 + args.info.AccessLevel.ToString());
+ tmp.AppendLine(Properties.Resources.ApiInfo8 + result.AccessLevel);
SetStatusLabelUrl();
tmp.AppendLine();
- tmp.AppendLine(Properties.Resources.ApiInfo9 + (args.info.MediaMaxCount < 0 ? Properties.Resources.ApiInfo91 : args.info.MediaMaxCount.ToString()));
- tmp.AppendLine(Properties.Resources.ApiInfo10 + (args.info.MediaRemainCount < 0 ? Properties.Resources.ApiInfo91 : args.info.MediaRemainCount.ToString()));
- tmp.AppendLine(Properties.Resources.ApiInfo11 + (args.info.MediaResetTime == new DateTime() ? Properties.Resources.ApiInfo91 : args.info.MediaResetTime.ToString()));
+ tmp.AppendLine(Properties.Resources.ApiInfo9 + (result.MediaUploadLimit == null ? Properties.Resources.ApiInfo91 : result.MediaUploadLimit.AccessLimitCount.ToString()));
+ tmp.AppendLine(Properties.Resources.ApiInfo10 + (result.MediaUploadLimit == null ? Properties.Resources.ApiInfo91 : result.MediaUploadLimit.AccessLimitRemain.ToString()));
+ tmp.AppendLine(Properties.Resources.ApiInfo11 + (result.MediaUploadLimit == null ? Properties.Resources.ApiInfo91 : result.MediaUploadLimit.AccessLimitResetDate.ToString()));
}
else
{
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
+using OpenTween.Api;
namespace OpenTween
{
HttpStatusCode res;
var content = "";
- MyCommon.TwitterApiInfo.Initialize();
+ MyCommon.TwitterApiInfo.Reset();
try
{
res = twCon.AuthUserAndPass(username, password, ref content);
//OAuth PIN Flow
bool res;
- MyCommon.TwitterApiInfo.Initialize();
+ MyCommon.TwitterApiInfo.Reset();
try
{
res = twCon.AuthGetRequestToken(ref pinPageUrl);
HttpStatusCode res;
var content = "";
- MyCommon.TwitterApiInfo.Initialize();
+ MyCommon.TwitterApiInfo.Reset();
try
{
res = twCon.AuthGetAccessToken(pinCode);
public void ClearAuthInfo()
{
Twitter.AccountState = MyCommon.ACCOUNT_STATE.Invalid;
- MyCommon.TwitterApiInfo.Initialize();
+ MyCommon.TwitterApiInfo.Reset();
twCon.ClearAuthInfo();
}
{
Twitter.AccountState = MyCommon.ACCOUNT_STATE.Invalid;
}
- MyCommon.TwitterApiInfo.Initialize();
+ MyCommon.TwitterApiInfo.Reset();
twCon.Initialize(token, tokenSecret, username, userId);
_uname = username.ToLower();
if (AppendSettingDialog.Instance.UserstreamStartup) this.ReconnectUserStream();
if (MyCommon._endingFlag) return "";
if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
- if (MyCommon.TwitterApiInfo.AccessLevel != ApiAccessLevel.None)
+ if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
{
- if (!MyCommon.TwitterApiInfo.IsDirectMessagePermission) return "Auth Err:try to re-authorization.";
+ return "Auth Err:try to re-authorization.";
}
postStr = postStr.Trim();
if (MyCommon._endingFlag) return "";
if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
- if (MyCommon.TwitterApiInfo.AccessLevel != ApiAccessLevel.None)
+ if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
{
- if (!MyCommon.TwitterApiInfo.IsDirectMessagePermission) return "Auth Err:try to re-authorization.";
+ return "Auth Err:try to re-authorization.";
}
HttpStatusCode res = HttpStatusCode.BadRequest;
if (MyCommon._endingFlag) return "";
if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
- if (MyCommon.TwitterApiInfo.AccessLevel != ApiAccessLevel.None)
+ if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
{
- if (!MyCommon.TwitterApiInfo.IsDirectMessagePermission) return "Auth Err:try to re-authorization.";
+ return "Auth Err:try to re-authorization.";
}
HttpStatusCode res = HttpStatusCode.BadRequest;
}
}
- public bool GetInfoApi(ApiInfo info)
+ public bool GetInfoApi()
{
if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return true;
}
catch(Exception)
{
- MyCommon.TwitterApiInfo.Initialize();
+ MyCommon.TwitterApiInfo.Reset();
return false;
}
try
{
var limit = MyCommon.CreateDataFromJson<TwitterDataModel.RateLimitStatus>(content);
- var arg = new ApiInformationChangedEventArgs();
- arg.ApiInfo.MaxCount = limit.HourlyLimit;
- arg.ApiInfo.RemainCount = limit.RemainingHits;
- arg.ApiInfo.ResetTime = MyCommon.DateTimeParse(limit.RestTime);
- arg.ApiInfo.ResetTimeInSeconds = limit.RestTimeInSeconds;
- if (info != null)
- {
- arg.ApiInfo.UsingCount = info.UsingCount;
-
- info.MaxCount = arg.ApiInfo.MaxCount;
- info.RemainCount = arg.ApiInfo.RemainCount;
- info.ResetTime = arg.ApiInfo.ResetTime;
- info.ResetTimeInSeconds = arg.ApiInfo.ResetTimeInSeconds;
- }
-
- if (ApiInformationChanged != null)
- {
- ApiInformationChanged(this, arg);
- }
- MyCommon.TwitterApiInfo.WriteBackEventArgs(arg);
+ MyCommon.TwitterApiInfo.UpdateFromApi(limit);
return true;
}
catch(Exception ex)
{
MyCommon.TraceOut(ex, MethodBase.GetCurrentMethod().Name + " " + content);
- MyCommon.TwitterApiInfo.Initialize();
+ MyCommon.TwitterApiInfo.Reset();
return false;
}
}
}
}
- public event EventHandler<ApiInformationChangedEventArgs> ApiInformationChanged;
-
- private void Twitter_ApiInformationChanged(object sender, ApiInformationChangedEventArgs e)
- {
- }
-
- public Twitter()
- {
- ApiInformationChanged += Twitter_ApiInformationChanged;
- }
-
#region "UserStream"
private string trackWord_ = "";
public string TrackWord