OSDN Git Service

API v1.1 に対応
authorKimura Youichi <kim.upsilon@bucyou.net>
Thu, 14 Feb 2013 10:11:31 +0000 (19:11 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Tue, 16 Apr 2013 20:29:00 +0000 (05:29 +0900)
ステータスバーの API レートリミット表示をクリックすると API v1 と API v1.1 を
切り替えることができます。

OpenTween.Tests/Api/TwitterApiStatusTest.cs
OpenTween/Api/TwitterApiStatus.cs
OpenTween/Api/TwitterApiStatus11.cs [new file with mode: 0644]
OpenTween/Connection/HttpTwitter.cs
OpenTween/DataModel.cs
OpenTween/MyCommon.cs
OpenTween/OpenTween.csproj
OpenTween/Resources/ChangeLog.txt
OpenTween/ToolStripAPIGauge.cs
OpenTween/Tween.cs
OpenTween/Twitter.cs

index 508a3ab..9ac2533 100644 (file)
@@ -83,7 +83,7 @@ namespace OpenTween.Api
         [TestCaseSource("ParseRateLimit_TestCase")]
         public void ParseRateLimitTest(IDictionary<string, string> header, ApiLimit expect)
         {
-            var limit = TwitterApiStatus.ParseRateLimit(header);
+            var limit = TwitterApiStatus.ParseRateLimit(header, "X-RateLimit");
             Assert.That(limit, Is.EqualTo(expect));
         }
 
@@ -116,7 +116,7 @@ namespace OpenTween.Api
         [TestCaseSource("ParseMediaRateLimit_TestCase")]
         public void ParseMediaRateLimitTest(IDictionary<string, string> header, ApiLimit expect)
         {
-            var limit = TwitterApiStatus.ParseMediaRateLimit(header);
+            var limit = TwitterApiStatus.ParseRateLimit(header, "X-MediaRateLimit-");
             Assert.That(limit, Is.EqualTo(expect));
         }
 
@@ -146,7 +146,7 @@ namespace OpenTween.Api
         [TestCaseSource("ParseAccessLevel_TestCase")]
         public void ParseAccessLevelTest(IDictionary<string, string> header, TwitterApiAccessLevel? expect)
         {
-            var accessLevel = TwitterApiStatus.ParseAccessLevel(header);
+            var accessLevel = TwitterApiStatus.ParseAccessLevel(header, "X-Access-Level");
             Assert.That(accessLevel, Is.EqualTo(expect));
         }
 
index 7c3dfe1..75b4c73 100644 (file)
@@ -60,24 +60,24 @@ namespace OpenTween.Api
 
         public void UpdateFromHeader(IDictionary<string, string> header)
         {
-            var rateLimit = TwitterApiStatus.ParseRateLimit(header);
+            var rateLimit = TwitterApiStatus.ParseRateLimit(header, "X-RateLimit-");
             if (rateLimit != null)
                 this.AccessLimit = rateLimit;
 
-            var mediaLimit = TwitterApiStatus.ParseMediaRateLimit(header);
+            var mediaLimit = TwitterApiStatus.ParseRateLimit(header, "X-MediaRateLimit-");
             if (mediaLimit != null)
                 this.MediaUploadLimit = mediaLimit;
 
-            var accessLevel = TwitterApiStatus.ParseAccessLevel(header);
+            var accessLevel = TwitterApiStatus.ParseAccessLevel(header, "X-Access-Level");
             if (accessLevel.HasValue)
                 this.AccessLevel = accessLevel.Value;
         }
 
-        internal static ApiLimit ParseRateLimit(IDictionary<string, string> header)
+        internal static ApiLimit ParseRateLimit(IDictionary<string, string> header, string prefix)
         {
-            var limitCount = ParseHeaderValue(header, "X-RateLimit-Limit") ?? -1;
-            var limitRemain = ParseHeaderValue(header, "X-RateLimit-Remaining") ?? -1;
-            var limitReset = ParseHeaderValue(header, "X-RateLimit-Reset") ?? -1;
+            var limitCount = ParseHeaderValue(header, prefix + "Limit") ?? -1;
+            var limitRemain = ParseHeaderValue(header, prefix + "Remaining") ?? -1;
+            var limitReset = ParseHeaderValue(header, prefix + "Reset") ?? -1;
 
             if (limitCount == -1 || limitRemain == -1 || limitReset == -1)
                 return null;
@@ -86,25 +86,12 @@ namespace OpenTween.Api
             return new ApiLimit(limitCount, limitRemain, limitResetDate);
         }
 
-        internal static ApiLimit ParseMediaRateLimit(IDictionary<string, string> header)
+        internal static TwitterApiAccessLevel? ParseAccessLevel(IDictionary<string, string> header, string headerName)
         {
-            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"))
+            if (!header.ContainsKey(headerName))
                 return null;
 
-            switch (header["X-Access-Level"])
+            switch (header[headerName])
             {
                 case "read-write-directmessages":
                 case "read-write-privatemessages":
@@ -117,7 +104,7 @@ namespace OpenTween.Api
                     // たまに出てくる空文字列は無視する
                     return null;
                 default:
-                    MyCommon.TraceOut("Unknown ApiAccessLevel:" + header["X-Access-Level"]);
+                    MyCommon.TraceOut("Unknown ApiAccessLevel:" + header[headerName]);
                     return TwitterApiAccessLevel.ReadWriteAndDirectMessage;
             }
         }
diff --git a/OpenTween/Api/TwitterApiStatus11.cs b/OpenTween/Api/TwitterApiStatus11.cs
new file mode 100644 (file)
index 0000000..1363dab
--- /dev/null
@@ -0,0 +1,113 @@
+// 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 TwitterApiStatus11
+    {
+        public TwitterApiAccessLevel AccessLevel { get; set; }
+        public EndpointLimits AccessLimit { get; private set; }
+        public ApiLimit MediaUploadLimit { get; set; }
+
+        public class AccessLimitUpdatedEventArgs : EventArgs
+        {
+            public readonly string EndpointName;
+
+            public AccessLimitUpdatedEventArgs(string endpointName)
+            {
+                this.EndpointName = endpointName;
+            }
+        }
+        public event EventHandler<AccessLimitUpdatedEventArgs> AccessLimitUpdated;
+
+        public TwitterApiStatus11()
+        {
+            this.AccessLimit = new EndpointLimits(this);
+        }
+
+        public void Reset()
+        {
+            this.AccessLevel = TwitterApiAccessLevel.Anonymous;
+            this.AccessLimit.Clear();
+            this.MediaUploadLimit = null;
+        }
+
+        public void UpdateFromHeader(IDictionary<string, string> header, string endpointName)
+        {
+            var rateLimit = TwitterApiStatus.ParseRateLimit(header, "X-Rate-Limit-");
+            if (rateLimit != null)
+                this.AccessLimit[endpointName] = rateLimit;
+
+            var mediaLimit = TwitterApiStatus.ParseRateLimit(header, "X-MediaRateLimit-");
+            if (mediaLimit != null)
+                this.MediaUploadLimit = mediaLimit;
+
+            var accessLevel = TwitterApiStatus.ParseAccessLevel(header, "X-Access-Level");
+            if (accessLevel.HasValue)
+                this.AccessLevel = accessLevel.Value;
+        }
+
+        protected virtual void OnAccessLimitUpdated(AccessLimitUpdatedEventArgs e)
+        {
+            if (this.AccessLimitUpdated != null)
+                this.AccessLimitUpdated(this, e);
+        }
+
+        public class EndpointLimits
+        {
+            public readonly TwitterApiStatus11 Owner;
+
+            private Dictionary<string, ApiLimit> innerDict = new Dictionary<string, ApiLimit>();
+
+            public EndpointLimits(TwitterApiStatus11 owner)
+            {
+                this.Owner = owner;
+            }
+
+            public ApiLimit this[string endpoint]
+            {
+                get
+                {
+                    if (this.innerDict.ContainsKey(endpoint))
+                        return this.innerDict[endpoint];
+
+                    return null;
+                }
+                set
+                {
+                    this.innerDict[endpoint] = value;
+                    this.Owner.OnAccessLimitUpdated(new AccessLimitUpdatedEventArgs(endpoint));
+                }
+            }
+
+            public void Clear()
+            {
+                this.innerDict.Clear();
+                this.Owner.OnAccessLimitUpdated(new AccessLimitUpdatedEventArgs(null));
+            }
+        }
+    }
+}
index fc3058c..d97ef02 100644 (file)
@@ -35,6 +35,15 @@ namespace OpenTween
 {
     public class HttpTwitter : ICloneable
     {
+        /// <summary>
+        /// API v1.1 を有効にする否か
+        /// </summary>
+        /// <remarks>
+        /// 旧APIが使用出来なくなったら消す予定。
+        /// 静的フィールドとしているのは TwitterUserstream クラスが Clone メソッドを使用しているため
+        /// </remarks>
+        public static bool API11Enabled { get; set; }
+
         //OAuth関連
         ///<summary>
         ///OAuthのアクセストークン取得先URI
@@ -71,11 +80,19 @@ namespace OpenTween
             {"X-RateLimit-Limit", ""},
             {"X-RateLimit-Remaining", ""},
             {"X-RateLimit-Reset", ""},
+            {"X-Rate-Limit-Limit", ""},
+            {"X-Rate-Limit-Remaining", ""},
+            {"X-Rate-Limit-Reset", ""},
             {"X-MediaRateLimit-Limit", ""},
             {"X-MediaRateLimit-Remaining", ""},
             {"X-MediaRateLimit-Reset", ""},
         };
 
+        static HttpTwitter()
+        {
+            HttpTwitter.API11Enabled = true;
+        }
+
         public void Initialize(string accessToken,
                                         string accessTokenSecret,
                                         string username,
@@ -197,11 +214,11 @@ namespace OpenTween
             //if (AppendSettingDialog.Instance.ShortenTco && AppendSettingDialog.Instance.UrlConvertAuto) param.Add("wrap_links", "true")
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/statuses/update.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/update.json" : "/1/statuses/update.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode UpdateStatusWithMedia(string status, long replyToId, FileInfo mediaFile, ref string content)
@@ -217,24 +234,28 @@ namespace OpenTween
             binary.Add(new KeyValuePair<string, FileInfo>("media[]", mediaFile));
 
             return httpCon.GetContent(PostMethod,
-                                      new Uri("https://upload.twitter.com/1/statuses/update_with_media.json"),
-                                      param,
-                                      binary,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                HttpTwitter.API11Enabled ? CreateTwitterUri("/1.1/statuses/update_with_media.json") : new Uri("https://upload.twitter.com/1/statuses/update_with_media.json"),
+                param,
+                binary,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/update_with_media") : GetApiCallback);
         }
 
         public HttpStatusCode DestroyStatus(long id)
         {
             string content = null;
 
+            var param = new Dictionary<string, string>();
+            if (HttpTwitter.API11Enabled)
+                param.Add("id", id.ToString());
+
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/statuses/destroy/" + id.ToString()+ ".json"),
-                                      null,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/destroy.json" : "/1/statuses/destroy/" + id + ".json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode SendDirectMessage(string status, string sendto, ref string content)
@@ -245,23 +266,27 @@ namespace OpenTween
             //if (AppendSettingDialog.Instance.ShortenTco && AppendSettingDialog.Instance.UrlConvertAuto) param.Add("wrap_links", "true")
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/direct_messages/new.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/direct_messages/new.json" : "/1/direct_messages/new.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode DestroyDirectMessage(long id)
         {
             string content = null;
 
+            var param = new Dictionary<string, string>();
+            if (HttpTwitter.API11Enabled)
+                param.Add("id", id.ToString());
+
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/direct_messages/destroy/" + id.ToString()+ ".json"),
-                                      null,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/direct_messages/destroy.json" : "/1/direct_messages/destroy/" + id + ".json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode RetweetStatus(long id, ref string content)
@@ -270,11 +295,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/statuses/retweet/" + id.ToString() + ".json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/retweet/" + id + ".json" : "/1/statuses/retweet/" + id + ".json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode ShowUserInfo(string screenName, ref string content)
@@ -283,11 +308,11 @@ namespace OpenTween
             param.Add("screen_name", screenName);
             param.Add("include_entities", "true");
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/users/show.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/users/show.json" : "/1/users/show.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/users/show/:id") : GetApiCallback);
         }
 
         public HttpStatusCode CreateFriendships(string screenName, ref string content)
@@ -296,11 +321,11 @@ namespace OpenTween
             param.Add("screen_name", screenName);
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/friendships/create.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/friendships/create.json" : "/1/friendships/create.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode DestroyFriendships(string screenName, ref string content)
@@ -309,11 +334,11 @@ namespace OpenTween
             param.Add("screen_name", screenName);
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/friendships/destroy.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/friendships/destroy.json" : "/1/friendships/destroy.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode CreateBlock(string screenName, ref string content)
@@ -322,11 +347,11 @@ namespace OpenTween
             param.Add("screen_name", screenName);
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/blocks/create.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/blocks/create.json" : "/1/blocks/create.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode DestroyBlock(string screenName, ref string content)
@@ -335,11 +360,11 @@ namespace OpenTween
             param.Add("screen_name", screenName);
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/blocks/destroy.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/blocks/destroy.json" : "/1/blocks/destroy.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode ReportSpam(string screenName, ref string content)
@@ -348,11 +373,11 @@ namespace OpenTween
             param.Add("screen_name", screenName);
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/report_spam.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/users/report_spam.json" : "/1/report_spam.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode ShowFriendships(string souceScreenName, string targetScreenName, ref string content)
@@ -362,11 +387,11 @@ namespace OpenTween
             param.Add("target_screen_name", targetScreenName);
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/friendships/show.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/friendships/show.json" : "/1/friendships/show.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/friendships/show") : GetApiCallback);
         }
 
         public HttpStatusCode ShowStatuses(long id, ref string content)
@@ -374,31 +399,39 @@ namespace OpenTween
             Dictionary<string, string> param = new Dictionary<string, string>();
             param.Add("include_entities", "true");
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/statuses/show/" + id.ToString() + ".json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/show/" + id + ".json" : "/1/statuses/show/" + id + ".json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/show/:id") : GetApiCallback);
         }
 
         public HttpStatusCode CreateFavorites(long id, ref string content)
         {
+            var param = new Dictionary<string, string>();
+            if (HttpTwitter.API11Enabled)
+                param.Add("id", id.ToString());
+
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/favorites/create/" + id.ToString() + ".json"),
-                                      null,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/favorites/create.json" : "/1/favorites/create/" + id + ".json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode DestroyFavorites(long id, ref string content)
         {
+            var param = new Dictionary<string, string>();
+            if (HttpTwitter.API11Enabled)
+                param.Add("id", id.ToString());
+
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/favorites/destroy/" + id.ToString() + ".json"),
-                                      null,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/favorites/destroy.json" : "/1/favorites/destroy/" + id + ".json"),
+                null,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode HomeTimeline(int count, long max_id, long since_id, ref string content)
@@ -414,11 +447,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/statuses/home_timeline.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/home_timeline.json" : "/1/statuses/home_timeline.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/home_timeline") : GetApiCallback);
         }
 
         public HttpStatusCode UserTimeline(long user_id, string screen_name, int count, long max_id, long since_id, ref string content)
@@ -443,11 +476,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/statuses/user_timeline.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/user_timeline.json" : "/1/statuses/user_timeline.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/user_timeline") : GetApiCallback);
         }
 
         public HttpStatusCode PublicTimeline(int count, long max_id, long since_id, ref string content)
@@ -462,12 +495,14 @@ namespace OpenTween
 
             param.Add("include_entities", "true");
 
+            // TODO: API v1.1 に存在しない API (旧 API で代替)
+
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/statuses/public_timeline.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri("/1/statuses/public_timeline.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                GetApiCallback);
         }
 
         public HttpStatusCode Mentions(int count, long max_id, long since_id, ref string content)
@@ -483,11 +518,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/statuses/mentions.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/mentions_timeline.json" : "/1/statuses/mentions.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/mentions_timeline") : GetApiCallback);
         }
 
         public HttpStatusCode DirectMessages(int count, long max_id, long since_id, ref string content)
@@ -502,11 +537,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/direct_messages.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/direct_messages.json" : "/1/direct_messages.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/direct_messages") : GetApiCallback);
         }
 
         public HttpStatusCode DirectMessagesSent(int count, long max_id, long since_id, ref string content)
@@ -521,11 +556,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/direct_messages/sent.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/direct_messages/sent.json" : "/1/direct_messages/sent.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/direct_messages/sent") : GetApiCallback);
         }
 
         public HttpStatusCode Favorites(int count, int page, ref string content)
@@ -541,11 +576,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/favorites.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/favorites/list.json" : "/1/favorites.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/favorites/list") : GetApiCallback);
         }
 
         public HttpStatusCode PhoenixSearch(string querystr, ref string content)
@@ -591,12 +626,12 @@ namespace OpenTween
                                          MyCommon.GetAssemblyName());
         }
 
-        public HttpStatusCode Search(string words, string lang, int rpp, int page, long sinceId, ref string content)
+        public HttpStatusCode Search(string words, string lang, int count, int page, long sinceId, ref string content)
         {
             Dictionary<string, string> param = new Dictionary<string, string>();
             if (!string.IsNullOrEmpty(words)) param.Add("q", words);
             if (!string.IsNullOrEmpty(lang)) param.Add("lang", lang);
-            if (rpp > 0) param.Add("rpp", rpp.ToString());
+            if (count > 0) param.Add(HttpTwitter.API11Enabled ? "count" : "rpp", count.ToString());
             if (page > 0) param.Add("page", page.ToString());
             if (sinceId > 0) param.Add("since_id", sinceId.ToString());
 
@@ -604,22 +639,22 @@ namespace OpenTween
 
             param.Add("result_type", "recent");
             param.Add("include_entities", "true");
-            return httpConVar.GetContent(GetMethod,
-                                         this.CreateTwitterSearchUri("/search.json"),
-                                         param,
-                                         out content,
-                                         null,
-                                         MyCommon.GetAssemblyName());
+            return httpCon.GetContent(GetMethod,
+                HttpTwitter.API11Enabled ? this.CreateTwitterUri("/1.1/search/tweets.json") : this.CreateTwitterSearchUri("/search.json"),
+                param,
+                ref content,
+                null,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/search/tweets") : GetApiCallback);
         }
 
         public HttpStatusCode SavedSearches(ref string content)
         {
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/saved_searches.json"),
-                                      null,
-                                      ref content,
-                                      null,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/saved_searches/list.json" : "/1/saved_searches.json"),
+                null,
+                ref content,
+                null,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/saved_searches/list") : GetApiCallback);
         }
 
         public HttpStatusCode FollowerIds(long cursor, ref string content)
@@ -628,11 +663,11 @@ namespace OpenTween
             param.Add("cursor", cursor.ToString());
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/followers/ids.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/followers/ids.json" : "/1/followers/ids.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/followers/ids") : GetApiCallback);
         }
 
         public HttpStatusCode NoRetweetIds(long cursor, ref string content)
@@ -641,21 +676,21 @@ namespace OpenTween
             param.Add("cursor", cursor.ToString());
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/friendships/no_retweet_ids.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/friendships/no_retweets/ids.json" : "/1/friendships/no_retweet_ids.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/friendships/no_retweets/ids") : GetApiCallback);
         }
 
         public HttpStatusCode RateLimitStatus(ref string content)
         {
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/account/rate_limit_status.json"),
-                                      null,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/application/rate_limit_status.json" : "/1/account/rate_limit_status.json"),
+                null,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/application/rate_limit_status") : GetApiCallback);
         }
 
         #region Lists
@@ -665,11 +700,11 @@ namespace OpenTween
             param.Add("screen_name", user);
             param.Add("cursor", cursor.ToString());
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/lists.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/list.json" : "/1/lists.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/list") : GetApiCallback);
         }
 
         public HttpStatusCode UpdateListID(string user, string list_id, string name, Boolean isPrivate, string description, ref string content)
@@ -686,11 +721,11 @@ namespace OpenTween
             if (description != null) param.Add("description", description);
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/lists/update.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/update.json" : "/1/lists/update.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode DeleteListID(string user, string list_id, ref string content)
@@ -700,11 +735,11 @@ namespace OpenTween
             param.Add("list_id", list_id);
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/lists/destroy.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/destroy.json" : "/1/lists/destroy.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode GetListsSubscriptions(string user, long cursor, ref string content)
@@ -713,11 +748,11 @@ namespace OpenTween
             param.Add("screen_name", user);
             param.Add("cursor", cursor.ToString());
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/lists/subscriptions.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/subscriptions.json" : "/1/lists/subscriptions.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/subscriptions") : GetApiCallback);
         }
 
         public HttpStatusCode GetListsStatuses(long userId, long list_id, int per_page, long max_id, long since_id, Boolean isRTinclude, ref string content)
@@ -726,8 +761,7 @@ namespace OpenTween
             Dictionary<string, string> param = new Dictionary<string, string>();
             param.Add("user_id", userId.ToString());
             param.Add("list_id", list_id.ToString());
-            if (isRTinclude)
-                param.Add("include_rts", "true");
+            param.Add("include_rts", isRTinclude ? "true" : "false");
             if (per_page > 0)
                 param.Add("per_page", per_page.ToString());
             if (max_id > 0)
@@ -737,11 +771,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/lists/statuses.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/statuses.json" : "/1/lists/statuses.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/statuses") : GetApiCallback);
         }
 
         public HttpStatusCode CreateLists(string listname, Boolean isPrivate, string description, ref string content)
@@ -757,11 +791,11 @@ namespace OpenTween
                 param.Add("description", description);
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/lists/create.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/create.json" : "/1/lists/create.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode GetListMembers(string user, string list_id, long cursor, ref string content)
@@ -771,11 +805,11 @@ namespace OpenTween
             param.Add("list_id", list_id);
             param.Add("cursor", cursor.ToString());
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/lists/members.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/members.json" : "/1/lists/members.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/members") : GetApiCallback);
         }
 
         public HttpStatusCode CreateListMembers(string list_id, string memberName, ref string content)
@@ -784,11 +818,11 @@ namespace OpenTween
             param.Add("list_id", list_id);
             param.Add("screen_name", memberName);
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/lists/members/create.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/members/create.json" : "/1/lists/members/create.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         //public HttpStatusCode CreateListMembers(string user, string list_id, string memberName, ref string content)
@@ -820,11 +854,11 @@ namespace OpenTween
             param.Add("screen_name", memberName);
             param.Add("list_id", list_id);
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/lists/members/destroy.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/members/destroy.json" : "/1/lists/members/destroy.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         //public HttpStatusCode DeleteListMembers(string user, string list_id, string memberName, ref string content)
@@ -858,17 +892,11 @@ namespace OpenTween
             param.Add("screen_name", memberName);
             param.Add("list_id", list_id);
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/lists/members/show.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
-            //return httpCon.GetContent(GetMethod,
-            //                          CreateTwitterUri("/1/" + user + "/" + list_id + "/members/" + id + ".json"),
-            //                          null,
-            //                          ref content,
-            //                          MyCommon.TwitterApiInfo.HttpHeaders,
-            //                          GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/members/show.json" : "/1/lists/members/show.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/members/show") : GetApiCallback);
         }
         #endregion
 
@@ -880,12 +908,14 @@ namespace OpenTween
             if (page > 0)
                 param.Add("page", page.ToString());
 
+            // TODO: API v1.1 に存在しない API (旧 API で代替)
+
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/statuses/" + statusid.ToString()+ "/retweeted_by/ids.json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri("/1/statuses/" + statusid + "/retweeted_by/ids.json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                GetApiCallback);
         }
 
         public HttpStatusCode UpdateProfile(string name, string url, string location, string description, ref string content)
@@ -899,11 +929,11 @@ namespace OpenTween
             param.Add("include_entities", "true");
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/account/update_profile.json"),
-                                      param,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/account/update_profile.json" : "/1/account/update_profile.json"),
+                param,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode UpdateProfileImage(FileInfo imageFile, ref string content)
@@ -912,12 +942,12 @@ namespace OpenTween
             binary.Add(new KeyValuePair<string, FileInfo>("image", imageFile));
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterUri("/1/account/update_profile_image.json"),
-                                      null,
-                                      binary,
-                                      ref content,
-                                      null,
-                                      null);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/account/update_profile_image.json" : "/1/account/update_profile_image.json"),
+                null,
+                binary,
+                ref content,
+                null,
+                null);
         }
 
         public HttpStatusCode GetRelatedResults(long id, ref string content)
@@ -927,42 +957,44 @@ namespace OpenTween
 
             param.Add("include_entities", "true");
 
+            // TODO: API v1.1 に存在しない API (旧 API で代替)
+
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/related_results/show/" + id.ToString()+ ".json"),
-                                      param,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri("/1/related_results/show/" + id + ".json"),
+                param,
+                ref content,
+                this.apiStatusHeaders,
+                GetApiCallback);
         }
 
         public HttpStatusCode GetBlockUserIds(ref string content)
         {
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/blocks/blocking/ids.json"),
-                                      null,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/blocks/ids.json" : "/1/blocks/blocking/ids.json"),
+                null,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/blocks/ids") : GetApiCallback);
         }
 
         public HttpStatusCode GetConfiguration(ref string content)
         {
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/help/configuration.json"),
-                                      null,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/help/configuration.json" : "/1/help/configuration.json"),
+                null,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/help/configuration") : GetApiCallback);
         }
 
         public HttpStatusCode VerifyCredentials(ref string content)
         {
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUri("/1/account/verify_credentials.json"),
-                                      null,
-                                      ref content,
-                                      this.apiStatusHeaders,
-                                      GetApiCallback);
+                CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/account/verify_credentials.json" : "/1/account/verify_credentials.json"),
+                null,
+                ref content,
+                this.apiStatusHeaders,
+                HttpTwitter.API11Enabled ? CreateApi11Calllback("/account/verify_credentials") : GetApiCallback);
         }
 
         #region Proxy API
@@ -1015,6 +1047,15 @@ namespace OpenTween
                 MyCommon.TwitterApiInfo.UpdateFromHeader(this.apiStatusHeaders);
         }
 
+        private CallbackDelegate CreateApi11Calllback(string endpointName)
+        {
+            return (object sender, ref HttpStatusCode code, ref string content) =>
+            {
+                if (code < HttpStatusCode.InternalServerError)
+                    MyCommon.TwitterApiInfo11.UpdateFromHeader(this.apiStatusHeaders, endpointName);
+            };
+        }
+
         public HttpStatusCode UserStream(ref Stream content,
                                          bool allAtReplies,
                                          string trackwords,
@@ -1029,10 +1070,10 @@ namespace OpenTween
                 param.Add("track", trackwords);
 
             return httpCon.GetContent(GetMethod,
-                                      CreateTwitterUserStreamUri("/2/user.json"),
-                                      param,
-                                      ref content,
-                                      userAgent);
+                CreateTwitterUserStreamUri(HttpTwitter.API11Enabled ? "/1.1/user.json" : "/2/user.json"),
+                param,
+                ref content,
+                userAgent);
         }
 
         public HttpStatusCode FilterStream(ref Stream content,
@@ -1046,10 +1087,10 @@ namespace OpenTween
                 param.Add("track", string.Join(",", trackwords.Split(" ".ToCharArray())));
 
             return httpCon.GetContent(PostMethod,
-                                      CreateTwitterStreamUri("/1/statuses/filter.json"),
-                                      param,
-                                      ref content,
-                                      userAgent);
+                CreateTwitterStreamUri(HttpTwitter.API11Enabled ? "/1.1/statuses/filter.json" : "/1/statuses/filter.json"),
+                param,
+                ref content,
+                userAgent);
         }
 
         public void RequestAbort()
index 2810e37..8df6604 100644 (file)
@@ -441,6 +441,27 @@ namespace OpenTween
         }
 
         [DataContract]
+        public class SearchResult11 // API v1.1
+        {
+            [DataMember(Name = "statuses")] public List<Status> Statuses;
+            [DataMember(Name = "search_metadata")] public SearchMetadata11 SearchMetadata;
+        }
+
+        [DataContract]
+        public class SearchMetadata11 // API v1.1
+        {
+            [DataMember(Name = "max_id")] public long MaxId;
+            [DataMember(Name = "since_id")] public long SinceId;
+            [DataMember(Name = "refresh_url")] public string RefreshUrl;
+            [DataMember(Name = "next_results")] public string NextResults;
+            [DataMember(Name = "count")] public int Count;
+            [DataMember(Name = "completed_in")] public double CompletedIn;
+            [DataMember(Name = "since_id_str")] public string SinceIdStr;
+            [DataMember(Name = "query")] public string Query;
+            [DataMember(Name = "max_id_str")] public string MaxIdStr;
+        }
+
+        [DataContract]
         public class SearchResult
         {
             [DataMember(Name = "completed_in")] public double CompletedIn;
index 1241b4a..3e95522 100644 (file)
@@ -680,6 +680,7 @@ namespace OpenTween
         }
 
         public static TwitterApiStatus TwitterApiInfo = new TwitterApiStatus();
+        public static TwitterApiStatus11 TwitterApiInfo11 = new TwitterApiStatus11();
 
         public static bool IsAnimatedGif(string filename)
         {
index 163d87e..ca5645f 100644 (file)
@@ -56,6 +56,7 @@
     <Compile Include="Api\ApiLimit.cs" />
     <Compile Include="Api\TwitterApiAccessLevel.cs" />
     <Compile Include="Api\TwitterApiStatus.cs" />
+    <Compile Include="Api\TwitterApiStatus11.cs" />
     <Compile Include="ApplicationEvents.cs">
       <SubType>Code</SubType>
     </Compile>
index 5fd163c..8bcab3c 100644 (file)
@@ -1,6 +1,10 @@
 更新履歴
 
 ==== Ver 1.1.0-beta1(2013/xx/xx)
+ * 当バージョンから Twitter API v1.1 に対応しています
+ * API v1.1 の使用に不都合がある場合は、ステータスバーのレートリミット表示をクリックすることで API v1 と切り替えることができます。
+
+ * NEW: API v1.1 に対応
  * NEW: タブの表示位置を画面上部に変更可能に (thx @aokomoriuta!)
  * NEW: mobile.twitter.com/<スクリーン名>/status/<ステータスID> のURLも関連発言表示の対象に追加
  * NEW: Favstarなどサードパーティ製サービスのパーマリンクURLも関連発言表示の対象に追加
index 3d34b83..14276c8 100644 (file)
@@ -40,12 +40,27 @@ namespace OpenTween
         public ToolStripAPIGauge()
             : base()
         {
-            this.Text = "API ???/???";
+            this.Text = "API v1.1 ???/???";
             this.ToolTipText = "API rest ???/???" + Environment.NewLine + "(reset after ??? minutes)";
 
             this.DisplayStyle = ToolStripItemDisplayStyle.Text;
         }
 
+        [DefaultValue(true)]
+        [RefreshProperties(RefreshProperties.Repaint)]
+        public bool API11Enabled
+        {
+            get { return this._API11Enabled; }
+            set
+            {
+                this._API11Enabled = value;
+
+                this.UpdateText();
+                this.Invalidate();
+            }
+        }
+        private bool _API11Enabled = true;
+
         /// <summary>
         /// ゲージに表示される横棒グラフの幅
         /// </summary>
@@ -167,10 +182,16 @@ namespace OpenTween
 
         protected virtual void UpdateText()
         {
+            string apiVersionText;
             string remainCountText;
             string maxCountText;
             string minuteText;
 
+            if (this._API11Enabled)
+                apiVersionText = "v1.1";
+            else
+                apiVersionText = "v1";
+
             if (this._ApiLimit == null)
             {
                 remainCountText = "???";
@@ -184,8 +205,8 @@ namespace OpenTween
                 minuteText = Math.Ceiling(this.remainMinutes).ToString();
             }
 
-            var textFormat = "API {0}/{1}";
-            this.Text = string.Format(textFormat, remainCountText, maxCountText);
+            var textFormat = "API {0} {1}/{2}";
+            this.Text = string.Format(textFormat, apiVersionText, remainCountText, maxCountText);
 
             var toolTipTextFormat =
                 "API rest {0}/{1}" + Environment.NewLine +
index c4055eb..477cc99 100644 (file)
@@ -555,7 +555,8 @@ namespace OpenTween
 
             SecurityManager = new InternetSecurityManager(PostBrowser);
 
-            MyCommon.TwitterApiInfo.AccessLimitUpdated += SetStatusLabelApiHandler;
+            MyCommon.TwitterApiInfo.AccessLimitUpdated += TwitterApiStatus_AccessLimitUpdated;
+            MyCommon.TwitterApiInfo11.AccessLimitUpdated += TwitterApiStatus_AccessLimitUpdated;
             Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
 
             string[] cmdArgs = Environment.GetCommandLineArgs();
@@ -9477,19 +9478,24 @@ namespace OpenTween
             return slbl.ToString();
         }
 
-        delegate void SetStatusLabelApiDelegate();
-
-        private void SetStatusLabelApiHandler(object sender, EventArgs e)
+        private void TwitterApiStatus_AccessLimitUpdated(object sender, EventArgs e)
         {
             try
             {
-                if (InvokeRequired && !IsDisposed)
+                if (this.InvokeRequired && !this.IsDisposed)
                 {
-                    Invoke(new SetStatusLabelApiDelegate(SetStatusLabelApi));
+                    this.Invoke((MethodInvoker)(() => this.TwitterApiStatus_AccessLimitUpdated(sender, e)));
                 }
                 else
                 {
-                    SetStatusLabelApi();
+                    if (sender is TwitterApiStatus11 && this._apiGauge.API11Enabled)
+                    {
+                        this._apiGauge.ApiLimit = MyCommon.TwitterApiInfo11.AccessLimit["/statuses/home_timeline"];
+                    }
+                    else if (sender is TwitterApiStatus && !this._apiGauge.API11Enabled)
+                    {
+                        this._apiGauge.ApiLimit = MyCommon.TwitterApiInfo.AccessLimit;
+                    }
                 }
             }
             catch (ObjectDisposedException)
@@ -9502,11 +9508,6 @@ namespace OpenTween
             }
         }
 
-        private void SetStatusLabelApi()
-        {
-            this._apiGauge.ApiLimit = MyCommon.TwitterApiInfo.AccessLimit;
-        }
-
         private void SetStatusLabelUrl()
         {
             StatusLabelUrl.Text = GetStatusLabelText();
@@ -12184,7 +12185,18 @@ namespace OpenTween
             this.gh.NotifyClicked += GrowlHelper_Callback;
 
             this._apiGauge = new ToolStripAPIGauge();
-            this._apiGauge.DoubleClick += this.ApiUsageInfoMenuItem_Click;
+            this._apiGauge.Click += (s, e) =>
+            {
+                var api11Enabled = !HttpTwitter.API11Enabled;
+
+                HttpTwitter.API11Enabled = api11Enabled;
+                (s as ToolStripAPIGauge).API11Enabled = api11Enabled;
+
+                if (api11Enabled)
+                    MyCommon.TwitterApiInfo11.Reset();
+                else
+                    MyCommon.TwitterApiInfo.Reset();
+            };
             this.StatusStrip1.Items.Insert(2, this._apiGauge);
 
             this.ReplaceAppName();
index cd86440..d871239 100644 (file)
@@ -170,12 +170,31 @@ namespace OpenTween
 
         //private List<PostClass> _deletemessages = new List<PostClass>();
 
+        public TwitterApiAccessLevel AccessLevel
+        {
+            get
+            {
+                if (HttpTwitter.API11Enabled)
+                    return MyCommon.TwitterApiInfo11.AccessLevel;
+                else
+                    return MyCommon.TwitterApiInfo.AccessLevel;
+            }
+        }
+
+        protected void ResetApiStatus()
+        {
+            if (HttpTwitter.API11Enabled)
+                MyCommon.TwitterApiInfo11.Reset();
+            else
+                MyCommon.TwitterApiInfo.Reset();
+        }
+
         public string Authenticate(string username, string password)
         {
             HttpStatusCode res;
             var content = "";
 
-            MyCommon.TwitterApiInfo.Reset();
+            this.ResetApiStatus();
             try
             {
                 res = twCon.AuthUserAndPass(username, password, ref content);
@@ -227,7 +246,7 @@ namespace OpenTween
             //OAuth PIN Flow
             bool res;
 
-            MyCommon.TwitterApiInfo.Reset();
+            this.ResetApiStatus();
             try
             {
                 res = twCon.AuthGetRequestToken(ref pinPageUrl);
@@ -245,7 +264,7 @@ namespace OpenTween
             HttpStatusCode res;
             var content = "";
 
-            MyCommon.TwitterApiInfo.Reset();
+            this.ResetApiStatus();
             try
             {
                 res = twCon.AuthGetAccessToken(pinCode);
@@ -295,7 +314,7 @@ namespace OpenTween
         public void ClearAuthInfo()
         {
             Twitter.AccountState = MyCommon.ACCOUNT_STATE.Invalid;
-            MyCommon.TwitterApiInfo.Reset();
+            this.ResetApiStatus();
             twCon.ClearAuthInfo();
         }
 
@@ -366,7 +385,7 @@ namespace OpenTween
             {
                 Twitter.AccountState = MyCommon.ACCOUNT_STATE.Invalid;
             }
-            MyCommon.TwitterApiInfo.Reset();
+            this.ResetApiStatus();
             twCon.Initialize(token, tokenSecret, username, userId);
             _uname = username.ToLower();
             if (AppendSettingDialog.Instance.UserstreamStartup) this.ReconnectUserStream();
@@ -752,7 +771,8 @@ namespace OpenTween
             if (MyCommon._endingFlag) return "";
 
             if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
-            if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
+
+            if (this.AccessLevel == TwitterApiAccessLevel.Read || this.AccessLevel == TwitterApiAccessLevel.ReadWrite)
             {
                 return "Auth Err:try to re-authorization.";
             }
@@ -970,7 +990,8 @@ namespace OpenTween
             if (MyCommon._endingFlag) return "";
 
             if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
-            if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
+
+            if (this.AccessLevel == TwitterApiAccessLevel.Read || this.AccessLevel == TwitterApiAccessLevel.ReadWrite)
             {
                 return "Auth Err:try to re-authorization.";
             }
@@ -2248,6 +2269,56 @@ namespace OpenTween
             return "";
         }
 
+        // API v1.1
+        private string CreatePostsFromSearch11Json(string content, TabClass tab, bool read, int count, ref long minimumId, bool more)
+        {
+            TwitterDataModel.SearchResult11 items;
+            try
+            {
+                items = MyCommon.CreateDataFromJson<TwitterDataModel.SearchResult11>(content);
+            }
+            catch (SerializationException ex)
+            {
+                MyCommon.TraceOut(ex.Message + Environment.NewLine + content);
+                return "Json Parse Error(DataContractJsonSerializer)";
+            }
+            catch (Exception ex)
+            {
+                MyCommon.TraceOut(ex, MethodBase.GetCurrentMethod().Name + " " + content);
+                return "Invalid Json!";
+            }
+            foreach (var result in items.Statuses)
+            {
+                PostClass post = null;
+                post = CreatePostsFromStatusData(result);
+                if (post == null) continue;
+
+                if (minimumId > post.StatusId) minimumId = post.StatusId;
+                if (!more && post.StatusId > tab.SinceId) tab.SinceId = post.StatusId;
+                //二重取得回避
+                lock (LockObj)
+                {
+                    if (tab == null)
+                    {
+                        if (TabInformations.GetInstance().ContainsKey(post.StatusId)) continue;
+                    }
+                    else
+                    {
+                        if (TabInformations.GetInstance().ContainsKey(post.StatusId, tab.TabName)) continue;
+                    }
+                }
+
+                post.IsRead = read;
+                if ((post.IsMe && !read) && this._readOwnPost) post.IsRead = true;
+
+                if (tab != null) post.RelTabName = tab.TabName;
+                //非同期アイコン取得&StatusDictionaryに追加
+                TabInformations.GetInstance().AddPost(post);
+            }
+
+            return "";
+        }
+
         private string CreatePostsFromSearchJson(string content, TabClass tab, bool read, int count, ref long minimumId, bool more)
         {
             TwitterDataModel.SearchResult items;
@@ -2715,7 +2786,10 @@ namespace OpenTween
 
             if (!TabInformations.GetInstance().ContainsTab(tab)) return "";
 
-            return this.CreatePostsFromSearchJson(content, tab, read, count, ref tab.OldestId, more);
+            if (HttpTwitter.API11Enabled)
+                return this.CreatePostsFromSearch11Json(content, tab, read, count, ref tab.OldestId, more);
+            else
+                return this.CreatePostsFromSearchJson(content, tab, read, count, ref tab.OldestId, more);
         }
 
         public string GetPhoenixSearch(bool read,
@@ -2918,7 +2992,8 @@ namespace OpenTween
             if (MyCommon._endingFlag) return "";
 
             if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
-            if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
+
+            if (this.AccessLevel == TwitterApiAccessLevel.Read || this.AccessLevel == TwitterApiAccessLevel.ReadWrite)
             {
                 return "Auth Err:try to re-authorization.";
             }
@@ -4088,7 +4163,7 @@ namespace OpenTween
             }
             catch(Exception)
             {
-                MyCommon.TwitterApiInfo.Reset();
+                this.ResetApiStatus();
                 return false;
             }