• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

dev


Commit MetaInfo

Revisionfba39b3cd0b3473de1ab22d7aace32fb15a25ef0 (tree)
Time2013-04-17 05:29:00
AuthorKimura Youichi <kim.upsilon@bucy...>
CommiterKimura Youichi

Log Message

API v1.1 に対応

ステータスバーの API レートリミット表示をクリックすると API v1 と API v1.1 を
切り替えることができます。

Change Summary

Incremental Difference

--- a/OpenTween.Tests/Api/TwitterApiStatusTest.cs
+++ b/OpenTween.Tests/Api/TwitterApiStatusTest.cs
@@ -83,7 +83,7 @@ namespace OpenTween.Api
8383 [TestCaseSource("ParseRateLimit_TestCase")]
8484 public void ParseRateLimitTest(IDictionary<string, string> header, ApiLimit expect)
8585 {
86- var limit = TwitterApiStatus.ParseRateLimit(header);
86+ var limit = TwitterApiStatus.ParseRateLimit(header, "X-RateLimit");
8787 Assert.That(limit, Is.EqualTo(expect));
8888 }
8989
@@ -116,7 +116,7 @@ namespace OpenTween.Api
116116 [TestCaseSource("ParseMediaRateLimit_TestCase")]
117117 public void ParseMediaRateLimitTest(IDictionary<string, string> header, ApiLimit expect)
118118 {
119- var limit = TwitterApiStatus.ParseMediaRateLimit(header);
119+ var limit = TwitterApiStatus.ParseRateLimit(header, "X-MediaRateLimit-");
120120 Assert.That(limit, Is.EqualTo(expect));
121121 }
122122
@@ -146,7 +146,7 @@ namespace OpenTween.Api
146146 [TestCaseSource("ParseAccessLevel_TestCase")]
147147 public void ParseAccessLevelTest(IDictionary<string, string> header, TwitterApiAccessLevel? expect)
148148 {
149- var accessLevel = TwitterApiStatus.ParseAccessLevel(header);
149+ var accessLevel = TwitterApiStatus.ParseAccessLevel(header, "X-Access-Level");
150150 Assert.That(accessLevel, Is.EqualTo(expect));
151151 }
152152
--- a/OpenTween/Api/TwitterApiStatus.cs
+++ b/OpenTween/Api/TwitterApiStatus.cs
@@ -60,24 +60,24 @@ namespace OpenTween.Api
6060
6161 public void UpdateFromHeader(IDictionary<string, string> header)
6262 {
63- var rateLimit = TwitterApiStatus.ParseRateLimit(header);
63+ var rateLimit = TwitterApiStatus.ParseRateLimit(header, "X-RateLimit-");
6464 if (rateLimit != null)
6565 this.AccessLimit = rateLimit;
6666
67- var mediaLimit = TwitterApiStatus.ParseMediaRateLimit(header);
67+ var mediaLimit = TwitterApiStatus.ParseRateLimit(header, "X-MediaRateLimit-");
6868 if (mediaLimit != null)
6969 this.MediaUploadLimit = mediaLimit;
7070
71- var accessLevel = TwitterApiStatus.ParseAccessLevel(header);
71+ var accessLevel = TwitterApiStatus.ParseAccessLevel(header, "X-Access-Level");
7272 if (accessLevel.HasValue)
7373 this.AccessLevel = accessLevel.Value;
7474 }
7575
76- internal static ApiLimit ParseRateLimit(IDictionary<string, string> header)
76+ internal static ApiLimit ParseRateLimit(IDictionary<string, string> header, string prefix)
7777 {
78- var limitCount = ParseHeaderValue(header, "X-RateLimit-Limit") ?? -1;
79- var limitRemain = ParseHeaderValue(header, "X-RateLimit-Remaining") ?? -1;
80- var limitReset = ParseHeaderValue(header, "X-RateLimit-Reset") ?? -1;
78+ var limitCount = ParseHeaderValue(header, prefix + "Limit") ?? -1;
79+ var limitRemain = ParseHeaderValue(header, prefix + "Remaining") ?? -1;
80+ var limitReset = ParseHeaderValue(header, prefix + "Reset") ?? -1;
8181
8282 if (limitCount == -1 || limitRemain == -1 || limitReset == -1)
8383 return null;
@@ -86,25 +86,12 @@ namespace OpenTween.Api
8686 return new ApiLimit(limitCount, limitRemain, limitResetDate);
8787 }
8888
89- internal static ApiLimit ParseMediaRateLimit(IDictionary<string, string> header)
89+ internal static TwitterApiAccessLevel? ParseAccessLevel(IDictionary<string, string> header, string headerName)
9090 {
91- var limitCount = ParseHeaderValue(header, "X-MediaRateLimit-Limit") ?? -1;
92- var limitRemain = ParseHeaderValue(header, "X-MediaRateLimit-Remaining") ?? -1;
93- var limitReset = ParseHeaderValue(header, "X-MediaRateLimit-Reset") ?? -1;
94-
95- if (limitCount == -1 || limitRemain == -1 || limitReset == -1)
96- return null;
97-
98- var limitResetDate = UnixEpoch.AddSeconds(limitReset).ToLocalTime();
99- return new ApiLimit(limitCount, limitRemain, limitResetDate);
100- }
101-
102- internal static TwitterApiAccessLevel? ParseAccessLevel(IDictionary<string, string> header)
103- {
104- if (!header.ContainsKey("X-Access-Level"))
91+ if (!header.ContainsKey(headerName))
10592 return null;
10693
107- switch (header["X-Access-Level"])
94+ switch (header[headerName])
10895 {
10996 case "read-write-directmessages":
11097 case "read-write-privatemessages":
@@ -117,7 +104,7 @@ namespace OpenTween.Api
117104 // たまに出てくる空文字列は無視する
118105 return null;
119106 default:
120- MyCommon.TraceOut("Unknown ApiAccessLevel:" + header["X-Access-Level"]);
107+ MyCommon.TraceOut("Unknown ApiAccessLevel:" + header[headerName]);
121108 return TwitterApiAccessLevel.ReadWriteAndDirectMessage;
122109 }
123110 }
--- /dev/null
+++ b/OpenTween/Api/TwitterApiStatus11.cs
@@ -0,0 +1,113 @@
1+// OpenTween - Client of Twitter
2+// Copyright (c) 2013 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3+// All rights reserved.
4+//
5+// This file is part of OpenTween.
6+//
7+// This program is free software; you can redistribute it and/or modify it
8+// under the terms of the GNU General Public License as published by the Free
9+// Software Foundation; either version 3 of the License, or (at your option)
10+// any later version.
11+//
12+// This program is distributed in the hope that it will be useful, but
13+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+// for more details.
16+//
17+// You should have received a copy of the GNU General Public License along
18+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20+// Boston, MA 02110-1301, USA.
21+
22+using System;
23+using System.Collections.Generic;
24+using System.Linq;
25+using System.Text;
26+
27+namespace OpenTween.Api
28+{
29+ public class TwitterApiStatus11
30+ {
31+ public TwitterApiAccessLevel AccessLevel { get; set; }
32+ public EndpointLimits AccessLimit { get; private set; }
33+ public ApiLimit MediaUploadLimit { get; set; }
34+
35+ public class AccessLimitUpdatedEventArgs : EventArgs
36+ {
37+ public readonly string EndpointName;
38+
39+ public AccessLimitUpdatedEventArgs(string endpointName)
40+ {
41+ this.EndpointName = endpointName;
42+ }
43+ }
44+ public event EventHandler<AccessLimitUpdatedEventArgs> AccessLimitUpdated;
45+
46+ public TwitterApiStatus11()
47+ {
48+ this.AccessLimit = new EndpointLimits(this);
49+ }
50+
51+ public void Reset()
52+ {
53+ this.AccessLevel = TwitterApiAccessLevel.Anonymous;
54+ this.AccessLimit.Clear();
55+ this.MediaUploadLimit = null;
56+ }
57+
58+ public void UpdateFromHeader(IDictionary<string, string> header, string endpointName)
59+ {
60+ var rateLimit = TwitterApiStatus.ParseRateLimit(header, "X-Rate-Limit-");
61+ if (rateLimit != null)
62+ this.AccessLimit[endpointName] = rateLimit;
63+
64+ var mediaLimit = TwitterApiStatus.ParseRateLimit(header, "X-MediaRateLimit-");
65+ if (mediaLimit != null)
66+ this.MediaUploadLimit = mediaLimit;
67+
68+ var accessLevel = TwitterApiStatus.ParseAccessLevel(header, "X-Access-Level");
69+ if (accessLevel.HasValue)
70+ this.AccessLevel = accessLevel.Value;
71+ }
72+
73+ protected virtual void OnAccessLimitUpdated(AccessLimitUpdatedEventArgs e)
74+ {
75+ if (this.AccessLimitUpdated != null)
76+ this.AccessLimitUpdated(this, e);
77+ }
78+
79+ public class EndpointLimits
80+ {
81+ public readonly TwitterApiStatus11 Owner;
82+
83+ private Dictionary<string, ApiLimit> innerDict = new Dictionary<string, ApiLimit>();
84+
85+ public EndpointLimits(TwitterApiStatus11 owner)
86+ {
87+ this.Owner = owner;
88+ }
89+
90+ public ApiLimit this[string endpoint]
91+ {
92+ get
93+ {
94+ if (this.innerDict.ContainsKey(endpoint))
95+ return this.innerDict[endpoint];
96+
97+ return null;
98+ }
99+ set
100+ {
101+ this.innerDict[endpoint] = value;
102+ this.Owner.OnAccessLimitUpdated(new AccessLimitUpdatedEventArgs(endpoint));
103+ }
104+ }
105+
106+ public void Clear()
107+ {
108+ this.innerDict.Clear();
109+ this.Owner.OnAccessLimitUpdated(new AccessLimitUpdatedEventArgs(null));
110+ }
111+ }
112+ }
113+}
--- a/OpenTween/Connection/HttpTwitter.cs
+++ b/OpenTween/Connection/HttpTwitter.cs
@@ -35,6 +35,15 @@ namespace OpenTween
3535 {
3636 public class HttpTwitter : ICloneable
3737 {
38+ /// <summary>
39+ /// API v1.1 を有効にする否か
40+ /// </summary>
41+ /// <remarks>
42+ /// 旧APIが使用出来なくなったら消す予定。
43+ /// 静的フィールドとしているのは TwitterUserstream クラスが Clone メソッドを使用しているため
44+ /// </remarks>
45+ public static bool API11Enabled { get; set; }
46+
3847 //OAuth関連
3948 ///<summary>
4049 ///OAuthのアクセストークン取得先URI
@@ -71,11 +80,19 @@ namespace OpenTween
7180 {"X-RateLimit-Limit", ""},
7281 {"X-RateLimit-Remaining", ""},
7382 {"X-RateLimit-Reset", ""},
83+ {"X-Rate-Limit-Limit", ""},
84+ {"X-Rate-Limit-Remaining", ""},
85+ {"X-Rate-Limit-Reset", ""},
7486 {"X-MediaRateLimit-Limit", ""},
7587 {"X-MediaRateLimit-Remaining", ""},
7688 {"X-MediaRateLimit-Reset", ""},
7789 };
7890
91+ static HttpTwitter()
92+ {
93+ HttpTwitter.API11Enabled = true;
94+ }
95+
7996 public void Initialize(string accessToken,
8097 string accessTokenSecret,
8198 string username,
@@ -197,11 +214,11 @@ namespace OpenTween
197214 //if (AppendSettingDialog.Instance.ShortenTco && AppendSettingDialog.Instance.UrlConvertAuto) param.Add("wrap_links", "true")
198215
199216 return httpCon.GetContent(PostMethod,
200- CreateTwitterUri("/1/statuses/update.json"),
201- param,
202- ref content,
203- null,
204- null);
217+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/update.json" : "/1/statuses/update.json"),
218+ param,
219+ ref content,
220+ null,
221+ null);
205222 }
206223
207224 public HttpStatusCode UpdateStatusWithMedia(string status, long replyToId, FileInfo mediaFile, ref string content)
@@ -217,24 +234,28 @@ namespace OpenTween
217234 binary.Add(new KeyValuePair<string, FileInfo>("media[]", mediaFile));
218235
219236 return httpCon.GetContent(PostMethod,
220- new Uri("https://upload.twitter.com/1/statuses/update_with_media.json"),
221- param,
222- binary,
223- ref content,
224- this.apiStatusHeaders,
225- GetApiCallback);
237+ HttpTwitter.API11Enabled ? CreateTwitterUri("/1.1/statuses/update_with_media.json") : new Uri("https://upload.twitter.com/1/statuses/update_with_media.json"),
238+ param,
239+ binary,
240+ ref content,
241+ this.apiStatusHeaders,
242+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/update_with_media") : GetApiCallback);
226243 }
227244
228245 public HttpStatusCode DestroyStatus(long id)
229246 {
230247 string content = null;
231248
249+ var param = new Dictionary<string, string>();
250+ if (HttpTwitter.API11Enabled)
251+ param.Add("id", id.ToString());
252+
232253 return httpCon.GetContent(PostMethod,
233- CreateTwitterUri("/1/statuses/destroy/" + id.ToString()+ ".json"),
234- null,
235- ref content,
236- null,
237- null);
254+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/destroy.json" : "/1/statuses/destroy/" + id + ".json"),
255+ param,
256+ ref content,
257+ null,
258+ null);
238259 }
239260
240261 public HttpStatusCode SendDirectMessage(string status, string sendto, ref string content)
@@ -245,23 +266,27 @@ namespace OpenTween
245266 //if (AppendSettingDialog.Instance.ShortenTco && AppendSettingDialog.Instance.UrlConvertAuto) param.Add("wrap_links", "true")
246267
247268 return httpCon.GetContent(PostMethod,
248- CreateTwitterUri("/1/direct_messages/new.json"),
249- param,
250- ref content,
251- null,
252- null);
269+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/direct_messages/new.json" : "/1/direct_messages/new.json"),
270+ param,
271+ ref content,
272+ null,
273+ null);
253274 }
254275
255276 public HttpStatusCode DestroyDirectMessage(long id)
256277 {
257278 string content = null;
258279
280+ var param = new Dictionary<string, string>();
281+ if (HttpTwitter.API11Enabled)
282+ param.Add("id", id.ToString());
283+
259284 return httpCon.GetContent(PostMethod,
260- CreateTwitterUri("/1/direct_messages/destroy/" + id.ToString()+ ".json"),
261- null,
262- ref content,
263- null,
264- null);
285+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/direct_messages/destroy.json" : "/1/direct_messages/destroy/" + id + ".json"),
286+ param,
287+ ref content,
288+ null,
289+ null);
265290 }
266291
267292 public HttpStatusCode RetweetStatus(long id, ref string content)
@@ -270,11 +295,11 @@ namespace OpenTween
270295 param.Add("include_entities", "true");
271296
272297 return httpCon.GetContent(PostMethod,
273- CreateTwitterUri("/1/statuses/retweet/" + id.ToString() + ".json"),
274- param,
275- ref content,
276- null,
277- null);
298+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/retweet/" + id + ".json" : "/1/statuses/retweet/" + id + ".json"),
299+ param,
300+ ref content,
301+ null,
302+ null);
278303 }
279304
280305 public HttpStatusCode ShowUserInfo(string screenName, ref string content)
@@ -283,11 +308,11 @@ namespace OpenTween
283308 param.Add("screen_name", screenName);
284309 param.Add("include_entities", "true");
285310 return httpCon.GetContent(GetMethod,
286- CreateTwitterUri("/1/users/show.json"),
287- param,
288- ref content,
289- this.apiStatusHeaders,
290- GetApiCallback);
311+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/users/show.json" : "/1/users/show.json"),
312+ param,
313+ ref content,
314+ this.apiStatusHeaders,
315+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/users/show/:id") : GetApiCallback);
291316 }
292317
293318 public HttpStatusCode CreateFriendships(string screenName, ref string content)
@@ -296,11 +321,11 @@ namespace OpenTween
296321 param.Add("screen_name", screenName);
297322
298323 return httpCon.GetContent(PostMethod,
299- CreateTwitterUri("/1/friendships/create.json"),
300- param,
301- ref content,
302- null,
303- null);
324+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/friendships/create.json" : "/1/friendships/create.json"),
325+ param,
326+ ref content,
327+ null,
328+ null);
304329 }
305330
306331 public HttpStatusCode DestroyFriendships(string screenName, ref string content)
@@ -309,11 +334,11 @@ namespace OpenTween
309334 param.Add("screen_name", screenName);
310335
311336 return httpCon.GetContent(PostMethod,
312- CreateTwitterUri("/1/friendships/destroy.json"),
313- param,
314- ref content,
315- null,
316- null);
337+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/friendships/destroy.json" : "/1/friendships/destroy.json"),
338+ param,
339+ ref content,
340+ null,
341+ null);
317342 }
318343
319344 public HttpStatusCode CreateBlock(string screenName, ref string content)
@@ -322,11 +347,11 @@ namespace OpenTween
322347 param.Add("screen_name", screenName);
323348
324349 return httpCon.GetContent(PostMethod,
325- CreateTwitterUri("/1/blocks/create.json"),
326- param,
327- ref content,
328- null,
329- null);
350+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/blocks/create.json" : "/1/blocks/create.json"),
351+ param,
352+ ref content,
353+ null,
354+ null);
330355 }
331356
332357 public HttpStatusCode DestroyBlock(string screenName, ref string content)
@@ -335,11 +360,11 @@ namespace OpenTween
335360 param.Add("screen_name", screenName);
336361
337362 return httpCon.GetContent(PostMethod,
338- CreateTwitterUri("/1/blocks/destroy.json"),
339- param,
340- ref content,
341- null,
342- null);
363+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/blocks/destroy.json" : "/1/blocks/destroy.json"),
364+ param,
365+ ref content,
366+ null,
367+ null);
343368 }
344369
345370 public HttpStatusCode ReportSpam(string screenName, ref string content)
@@ -348,11 +373,11 @@ namespace OpenTween
348373 param.Add("screen_name", screenName);
349374
350375 return httpCon.GetContent(PostMethod,
351- CreateTwitterUri("/1/report_spam.json"),
352- param,
353- ref content,
354- null,
355- null);
376+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/users/report_spam.json" : "/1/report_spam.json"),
377+ param,
378+ ref content,
379+ null,
380+ null);
356381 }
357382
358383 public HttpStatusCode ShowFriendships(string souceScreenName, string targetScreenName, ref string content)
@@ -362,11 +387,11 @@ namespace OpenTween
362387 param.Add("target_screen_name", targetScreenName);
363388
364389 return httpCon.GetContent(GetMethod,
365- CreateTwitterUri("/1/friendships/show.json"),
366- param,
367- ref content,
368- this.apiStatusHeaders,
369- GetApiCallback);
390+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/friendships/show.json" : "/1/friendships/show.json"),
391+ param,
392+ ref content,
393+ this.apiStatusHeaders,
394+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/friendships/show") : GetApiCallback);
370395 }
371396
372397 public HttpStatusCode ShowStatuses(long id, ref string content)
@@ -374,31 +399,39 @@ namespace OpenTween
374399 Dictionary<string, string> param = new Dictionary<string, string>();
375400 param.Add("include_entities", "true");
376401 return httpCon.GetContent(GetMethod,
377- CreateTwitterUri("/1/statuses/show/" + id.ToString() + ".json"),
378- param,
379- ref content,
380- this.apiStatusHeaders,
381- GetApiCallback);
402+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/show/" + id + ".json" : "/1/statuses/show/" + id + ".json"),
403+ param,
404+ ref content,
405+ this.apiStatusHeaders,
406+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/show/:id") : GetApiCallback);
382407 }
383408
384409 public HttpStatusCode CreateFavorites(long id, ref string content)
385410 {
411+ var param = new Dictionary<string, string>();
412+ if (HttpTwitter.API11Enabled)
413+ param.Add("id", id.ToString());
414+
386415 return httpCon.GetContent(PostMethod,
387- CreateTwitterUri("/1/favorites/create/" + id.ToString() + ".json"),
388- null,
389- ref content,
390- null,
391- null);
416+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/favorites/create.json" : "/1/favorites/create/" + id + ".json"),
417+ param,
418+ ref content,
419+ null,
420+ null);
392421 }
393422
394423 public HttpStatusCode DestroyFavorites(long id, ref string content)
395424 {
425+ var param = new Dictionary<string, string>();
426+ if (HttpTwitter.API11Enabled)
427+ param.Add("id", id.ToString());
428+
396429 return httpCon.GetContent(PostMethod,
397- CreateTwitterUri("/1/favorites/destroy/" + id.ToString() + ".json"),
398- null,
399- ref content,
400- null,
401- null);
430+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/favorites/destroy.json" : "/1/favorites/destroy/" + id + ".json"),
431+ null,
432+ ref content,
433+ null,
434+ null);
402435 }
403436
404437 public HttpStatusCode HomeTimeline(int count, long max_id, long since_id, ref string content)
@@ -414,11 +447,11 @@ namespace OpenTween
414447 param.Add("include_entities", "true");
415448
416449 return httpCon.GetContent(GetMethod,
417- CreateTwitterUri("/1/statuses/home_timeline.json"),
418- param,
419- ref content,
420- this.apiStatusHeaders,
421- GetApiCallback);
450+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/home_timeline.json" : "/1/statuses/home_timeline.json"),
451+ param,
452+ ref content,
453+ this.apiStatusHeaders,
454+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/home_timeline") : GetApiCallback);
422455 }
423456
424457 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
443476 param.Add("include_entities", "true");
444477
445478 return httpCon.GetContent(GetMethod,
446- CreateTwitterUri("/1/statuses/user_timeline.json"),
447- param,
448- ref content,
449- this.apiStatusHeaders,
450- GetApiCallback);
479+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/user_timeline.json" : "/1/statuses/user_timeline.json"),
480+ param,
481+ ref content,
482+ this.apiStatusHeaders,
483+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/user_timeline") : GetApiCallback);
451484 }
452485
453486 public HttpStatusCode PublicTimeline(int count, long max_id, long since_id, ref string content)
@@ -462,12 +495,14 @@ namespace OpenTween
462495
463496 param.Add("include_entities", "true");
464497
498+ // TODO: API v1.1 に存在しない API (旧 API で代替)
499+
465500 return httpCon.GetContent(GetMethod,
466- CreateTwitterUri("/1/statuses/public_timeline.json"),
467- param,
468- ref content,
469- this.apiStatusHeaders,
470- GetApiCallback);
501+ CreateTwitterUri("/1/statuses/public_timeline.json"),
502+ param,
503+ ref content,
504+ this.apiStatusHeaders,
505+ GetApiCallback);
471506 }
472507
473508 public HttpStatusCode Mentions(int count, long max_id, long since_id, ref string content)
@@ -483,11 +518,11 @@ namespace OpenTween
483518 param.Add("include_entities", "true");
484519
485520 return httpCon.GetContent(GetMethod,
486- CreateTwitterUri("/1/statuses/mentions.json"),
487- param,
488- ref content,
489- this.apiStatusHeaders,
490- GetApiCallback);
521+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/statuses/mentions_timeline.json" : "/1/statuses/mentions.json"),
522+ param,
523+ ref content,
524+ this.apiStatusHeaders,
525+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/statuses/mentions_timeline") : GetApiCallback);
491526 }
492527
493528 public HttpStatusCode DirectMessages(int count, long max_id, long since_id, ref string content)
@@ -502,11 +537,11 @@ namespace OpenTween
502537 param.Add("include_entities", "true");
503538
504539 return httpCon.GetContent(GetMethod,
505- CreateTwitterUri("/1/direct_messages.json"),
506- param,
507- ref content,
508- this.apiStatusHeaders,
509- GetApiCallback);
540+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/direct_messages.json" : "/1/direct_messages.json"),
541+ param,
542+ ref content,
543+ this.apiStatusHeaders,
544+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/direct_messages") : GetApiCallback);
510545 }
511546
512547 public HttpStatusCode DirectMessagesSent(int count, long max_id, long since_id, ref string content)
@@ -521,11 +556,11 @@ namespace OpenTween
521556 param.Add("include_entities", "true");
522557
523558 return httpCon.GetContent(GetMethod,
524- CreateTwitterUri("/1/direct_messages/sent.json"),
525- param,
526- ref content,
527- this.apiStatusHeaders,
528- GetApiCallback);
559+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/direct_messages/sent.json" : "/1/direct_messages/sent.json"),
560+ param,
561+ ref content,
562+ this.apiStatusHeaders,
563+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/direct_messages/sent") : GetApiCallback);
529564 }
530565
531566 public HttpStatusCode Favorites(int count, int page, ref string content)
@@ -541,11 +576,11 @@ namespace OpenTween
541576 param.Add("include_entities", "true");
542577
543578 return httpCon.GetContent(GetMethod,
544- CreateTwitterUri("/1/favorites.json"),
545- param,
546- ref content,
547- this.apiStatusHeaders,
548- GetApiCallback);
579+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/favorites/list.json" : "/1/favorites.json"),
580+ param,
581+ ref content,
582+ this.apiStatusHeaders,
583+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/favorites/list") : GetApiCallback);
549584 }
550585
551586 public HttpStatusCode PhoenixSearch(string querystr, ref string content)
@@ -591,12 +626,12 @@ namespace OpenTween
591626 MyCommon.GetAssemblyName());
592627 }
593628
594- public HttpStatusCode Search(string words, string lang, int rpp, int page, long sinceId, ref string content)
629+ public HttpStatusCode Search(string words, string lang, int count, int page, long sinceId, ref string content)
595630 {
596631 Dictionary<string, string> param = new Dictionary<string, string>();
597632 if (!string.IsNullOrEmpty(words)) param.Add("q", words);
598633 if (!string.IsNullOrEmpty(lang)) param.Add("lang", lang);
599- if (rpp > 0) param.Add("rpp", rpp.ToString());
634+ if (count > 0) param.Add(HttpTwitter.API11Enabled ? "count" : "rpp", count.ToString());
600635 if (page > 0) param.Add("page", page.ToString());
601636 if (sinceId > 0) param.Add("since_id", sinceId.ToString());
602637
@@ -604,22 +639,22 @@ namespace OpenTween
604639
605640 param.Add("result_type", "recent");
606641 param.Add("include_entities", "true");
607- return httpConVar.GetContent(GetMethod,
608- this.CreateTwitterSearchUri("/search.json"),
609- param,
610- out content,
611- null,
612- MyCommon.GetAssemblyName());
642+ return httpCon.GetContent(GetMethod,
643+ HttpTwitter.API11Enabled ? this.CreateTwitterUri("/1.1/search/tweets.json") : this.CreateTwitterSearchUri("/search.json"),
644+ param,
645+ ref content,
646+ null,
647+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/search/tweets") : GetApiCallback);
613648 }
614649
615650 public HttpStatusCode SavedSearches(ref string content)
616651 {
617652 return httpCon.GetContent(GetMethod,
618- CreateTwitterUri("/1/saved_searches.json"),
619- null,
620- ref content,
621- null,
622- GetApiCallback);
653+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/saved_searches/list.json" : "/1/saved_searches.json"),
654+ null,
655+ ref content,
656+ null,
657+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/saved_searches/list") : GetApiCallback);
623658 }
624659
625660 public HttpStatusCode FollowerIds(long cursor, ref string content)
@@ -628,11 +663,11 @@ namespace OpenTween
628663 param.Add("cursor", cursor.ToString());
629664
630665 return httpCon.GetContent(GetMethod,
631- CreateTwitterUri("/1/followers/ids.json"),
632- param,
633- ref content,
634- this.apiStatusHeaders,
635- GetApiCallback);
666+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/followers/ids.json" : "/1/followers/ids.json"),
667+ param,
668+ ref content,
669+ this.apiStatusHeaders,
670+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/followers/ids") : GetApiCallback);
636671 }
637672
638673 public HttpStatusCode NoRetweetIds(long cursor, ref string content)
@@ -641,21 +676,21 @@ namespace OpenTween
641676 param.Add("cursor", cursor.ToString());
642677
643678 return httpCon.GetContent(GetMethod,
644- CreateTwitterUri("/1/friendships/no_retweet_ids.json"),
645- param,
646- ref content,
647- this.apiStatusHeaders,
648- GetApiCallback);
679+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/friendships/no_retweets/ids.json" : "/1/friendships/no_retweet_ids.json"),
680+ param,
681+ ref content,
682+ this.apiStatusHeaders,
683+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/friendships/no_retweets/ids") : GetApiCallback);
649684 }
650685
651686 public HttpStatusCode RateLimitStatus(ref string content)
652687 {
653688 return httpCon.GetContent(GetMethod,
654- CreateTwitterUri("/1/account/rate_limit_status.json"),
655- null,
656- ref content,
657- this.apiStatusHeaders,
658- GetApiCallback);
689+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/application/rate_limit_status.json" : "/1/account/rate_limit_status.json"),
690+ null,
691+ ref content,
692+ this.apiStatusHeaders,
693+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/application/rate_limit_status") : GetApiCallback);
659694 }
660695
661696 #region Lists
@@ -665,11 +700,11 @@ namespace OpenTween
665700 param.Add("screen_name", user);
666701 param.Add("cursor", cursor.ToString());
667702 return httpCon.GetContent(GetMethod,
668- CreateTwitterUri("/1/lists.json"),
669- param,
670- ref content,
671- this.apiStatusHeaders,
672- GetApiCallback);
703+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/list.json" : "/1/lists.json"),
704+ param,
705+ ref content,
706+ this.apiStatusHeaders,
707+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/list") : GetApiCallback);
673708 }
674709
675710 public HttpStatusCode UpdateListID(string user, string list_id, string name, Boolean isPrivate, string description, ref string content)
@@ -686,11 +721,11 @@ namespace OpenTween
686721 if (description != null) param.Add("description", description);
687722
688723 return httpCon.GetContent(PostMethod,
689- CreateTwitterUri("/1/lists/update.json"),
690- param,
691- ref content,
692- null,
693- null);
724+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/update.json" : "/1/lists/update.json"),
725+ param,
726+ ref content,
727+ null,
728+ null);
694729 }
695730
696731 public HttpStatusCode DeleteListID(string user, string list_id, ref string content)
@@ -700,11 +735,11 @@ namespace OpenTween
700735 param.Add("list_id", list_id);
701736
702737 return httpCon.GetContent(PostMethod,
703- CreateTwitterUri("/1/lists/destroy.json"),
704- param,
705- ref content,
706- null,
707- null);
738+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/destroy.json" : "/1/lists/destroy.json"),
739+ param,
740+ ref content,
741+ null,
742+ null);
708743 }
709744
710745 public HttpStatusCode GetListsSubscriptions(string user, long cursor, ref string content)
@@ -713,11 +748,11 @@ namespace OpenTween
713748 param.Add("screen_name", user);
714749 param.Add("cursor", cursor.ToString());
715750 return httpCon.GetContent(GetMethod,
716- CreateTwitterUri("/1/lists/subscriptions.json"),
717- param,
718- ref content,
719- this.apiStatusHeaders,
720- GetApiCallback);
751+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/subscriptions.json" : "/1/lists/subscriptions.json"),
752+ param,
753+ ref content,
754+ this.apiStatusHeaders,
755+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/subscriptions") : GetApiCallback);
721756 }
722757
723758 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
726761 Dictionary<string, string> param = new Dictionary<string, string>();
727762 param.Add("user_id", userId.ToString());
728763 param.Add("list_id", list_id.ToString());
729- if (isRTinclude)
730- param.Add("include_rts", "true");
764+ param.Add("include_rts", isRTinclude ? "true" : "false");
731765 if (per_page > 0)
732766 param.Add("per_page", per_page.ToString());
733767 if (max_id > 0)
@@ -737,11 +771,11 @@ namespace OpenTween
737771 param.Add("include_entities", "true");
738772
739773 return httpCon.GetContent(GetMethod,
740- CreateTwitterUri("/1/lists/statuses.json"),
741- param,
742- ref content,
743- this.apiStatusHeaders,
744- GetApiCallback);
774+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/statuses.json" : "/1/lists/statuses.json"),
775+ param,
776+ ref content,
777+ this.apiStatusHeaders,
778+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/statuses") : GetApiCallback);
745779 }
746780
747781 public HttpStatusCode CreateLists(string listname, Boolean isPrivate, string description, ref string content)
@@ -757,11 +791,11 @@ namespace OpenTween
757791 param.Add("description", description);
758792
759793 return httpCon.GetContent(PostMethod,
760- CreateTwitterUri("/1/lists/create.json"),
761- param,
762- ref content,
763- null,
764- null);
794+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/create.json" : "/1/lists/create.json"),
795+ param,
796+ ref content,
797+ null,
798+ null);
765799 }
766800
767801 public HttpStatusCode GetListMembers(string user, string list_id, long cursor, ref string content)
@@ -771,11 +805,11 @@ namespace OpenTween
771805 param.Add("list_id", list_id);
772806 param.Add("cursor", cursor.ToString());
773807 return httpCon.GetContent(GetMethod,
774- CreateTwitterUri("/1/lists/members.json"),
775- param,
776- ref content,
777- this.apiStatusHeaders,
778- GetApiCallback);
808+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/members.json" : "/1/lists/members.json"),
809+ param,
810+ ref content,
811+ this.apiStatusHeaders,
812+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/members") : GetApiCallback);
779813 }
780814
781815 public HttpStatusCode CreateListMembers(string list_id, string memberName, ref string content)
@@ -784,11 +818,11 @@ namespace OpenTween
784818 param.Add("list_id", list_id);
785819 param.Add("screen_name", memberName);
786820 return httpCon.GetContent(PostMethod,
787- CreateTwitterUri("/1/lists/members/create.json"),
788- param,
789- ref content,
790- null,
791- null);
821+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/members/create.json" : "/1/lists/members/create.json"),
822+ param,
823+ ref content,
824+ null,
825+ null);
792826 }
793827
794828 //public HttpStatusCode CreateListMembers(string user, string list_id, string memberName, ref string content)
@@ -820,11 +854,11 @@ namespace OpenTween
820854 param.Add("screen_name", memberName);
821855 param.Add("list_id", list_id);
822856 return httpCon.GetContent(PostMethod,
823- CreateTwitterUri("/1/lists/members/destroy.json"),
824- param,
825- ref content,
826- null,
827- null);
857+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/members/destroy.json" : "/1/lists/members/destroy.json"),
858+ param,
859+ ref content,
860+ null,
861+ null);
828862 }
829863
830864 //public HttpStatusCode DeleteListMembers(string user, string list_id, string memberName, ref string content)
@@ -858,17 +892,11 @@ namespace OpenTween
858892 param.Add("screen_name", memberName);
859893 param.Add("list_id", list_id);
860894 return httpCon.GetContent(GetMethod,
861- CreateTwitterUri("/1/lists/members/show.json"),
862- param,
863- ref content,
864- this.apiStatusHeaders,
865- GetApiCallback);
866- //return httpCon.GetContent(GetMethod,
867- // CreateTwitterUri("/1/" + user + "/" + list_id + "/members/" + id + ".json"),
868- // null,
869- // ref content,
870- // MyCommon.TwitterApiInfo.HttpHeaders,
871- // GetApiCallback);
895+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/lists/members/show.json" : "/1/lists/members/show.json"),
896+ param,
897+ ref content,
898+ this.apiStatusHeaders,
899+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/lists/members/show") : GetApiCallback);
872900 }
873901 #endregion
874902
@@ -880,12 +908,14 @@ namespace OpenTween
880908 if (page > 0)
881909 param.Add("page", page.ToString());
882910
911+ // TODO: API v1.1 に存在しない API (旧 API で代替)
912+
883913 return httpCon.GetContent(GetMethod,
884- CreateTwitterUri("/1/statuses/" + statusid.ToString()+ "/retweeted_by/ids.json"),
885- param,
886- ref content,
887- this.apiStatusHeaders,
888- GetApiCallback);
914+ CreateTwitterUri("/1/statuses/" + statusid + "/retweeted_by/ids.json"),
915+ param,
916+ ref content,
917+ this.apiStatusHeaders,
918+ GetApiCallback);
889919 }
890920
891921 public HttpStatusCode UpdateProfile(string name, string url, string location, string description, ref string content)
@@ -899,11 +929,11 @@ namespace OpenTween
899929 param.Add("include_entities", "true");
900930
901931 return httpCon.GetContent(PostMethod,
902- CreateTwitterUri("/1/account/update_profile.json"),
903- param,
904- ref content,
905- null,
906- null);
932+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/account/update_profile.json" : "/1/account/update_profile.json"),
933+ param,
934+ ref content,
935+ null,
936+ null);
907937 }
908938
909939 public HttpStatusCode UpdateProfileImage(FileInfo imageFile, ref string content)
@@ -912,12 +942,12 @@ namespace OpenTween
912942 binary.Add(new KeyValuePair<string, FileInfo>("image", imageFile));
913943
914944 return httpCon.GetContent(PostMethod,
915- CreateTwitterUri("/1/account/update_profile_image.json"),
916- null,
917- binary,
918- ref content,
919- null,
920- null);
945+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/account/update_profile_image.json" : "/1/account/update_profile_image.json"),
946+ null,
947+ binary,
948+ ref content,
949+ null,
950+ null);
921951 }
922952
923953 public HttpStatusCode GetRelatedResults(long id, ref string content)
@@ -927,42 +957,44 @@ namespace OpenTween
927957
928958 param.Add("include_entities", "true");
929959
960+ // TODO: API v1.1 に存在しない API (旧 API で代替)
961+
930962 return httpCon.GetContent(GetMethod,
931- CreateTwitterUri("/1/related_results/show/" + id.ToString()+ ".json"),
932- param,
933- ref content,
934- this.apiStatusHeaders,
935- GetApiCallback);
963+ CreateTwitterUri("/1/related_results/show/" + id + ".json"),
964+ param,
965+ ref content,
966+ this.apiStatusHeaders,
967+ GetApiCallback);
936968 }
937969
938970 public HttpStatusCode GetBlockUserIds(ref string content)
939971 {
940972 return httpCon.GetContent(GetMethod,
941- CreateTwitterUri("/1/blocks/blocking/ids.json"),
942- null,
943- ref content,
944- this.apiStatusHeaders,
945- GetApiCallback);
973+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/blocks/ids.json" : "/1/blocks/blocking/ids.json"),
974+ null,
975+ ref content,
976+ this.apiStatusHeaders,
977+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/blocks/ids") : GetApiCallback);
946978 }
947979
948980 public HttpStatusCode GetConfiguration(ref string content)
949981 {
950982 return httpCon.GetContent(GetMethod,
951- CreateTwitterUri("/1/help/configuration.json"),
952- null,
953- ref content,
954- this.apiStatusHeaders,
955- GetApiCallback);
983+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/help/configuration.json" : "/1/help/configuration.json"),
984+ null,
985+ ref content,
986+ this.apiStatusHeaders,
987+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/help/configuration") : GetApiCallback);
956988 }
957989
958990 public HttpStatusCode VerifyCredentials(ref string content)
959991 {
960992 return httpCon.GetContent(GetMethod,
961- CreateTwitterUri("/1/account/verify_credentials.json"),
962- null,
963- ref content,
964- this.apiStatusHeaders,
965- GetApiCallback);
993+ CreateTwitterUri(HttpTwitter.API11Enabled ? "/1.1/account/verify_credentials.json" : "/1/account/verify_credentials.json"),
994+ null,
995+ ref content,
996+ this.apiStatusHeaders,
997+ HttpTwitter.API11Enabled ? CreateApi11Calllback("/account/verify_credentials") : GetApiCallback);
966998 }
967999
9681000 #region Proxy API
@@ -1015,6 +1047,15 @@ namespace OpenTween
10151047 MyCommon.TwitterApiInfo.UpdateFromHeader(this.apiStatusHeaders);
10161048 }
10171049
1050+ private CallbackDelegate CreateApi11Calllback(string endpointName)
1051+ {
1052+ return (object sender, ref HttpStatusCode code, ref string content) =>
1053+ {
1054+ if (code < HttpStatusCode.InternalServerError)
1055+ MyCommon.TwitterApiInfo11.UpdateFromHeader(this.apiStatusHeaders, endpointName);
1056+ };
1057+ }
1058+
10181059 public HttpStatusCode UserStream(ref Stream content,
10191060 bool allAtReplies,
10201061 string trackwords,
@@ -1029,10 +1070,10 @@ namespace OpenTween
10291070 param.Add("track", trackwords);
10301071
10311072 return httpCon.GetContent(GetMethod,
1032- CreateTwitterUserStreamUri("/2/user.json"),
1033- param,
1034- ref content,
1035- userAgent);
1073+ CreateTwitterUserStreamUri(HttpTwitter.API11Enabled ? "/1.1/user.json" : "/2/user.json"),
1074+ param,
1075+ ref content,
1076+ userAgent);
10361077 }
10371078
10381079 public HttpStatusCode FilterStream(ref Stream content,
@@ -1046,10 +1087,10 @@ namespace OpenTween
10461087 param.Add("track", string.Join(",", trackwords.Split(" ".ToCharArray())));
10471088
10481089 return httpCon.GetContent(PostMethod,
1049- CreateTwitterStreamUri("/1/statuses/filter.json"),
1050- param,
1051- ref content,
1052- userAgent);
1090+ CreateTwitterStreamUri(HttpTwitter.API11Enabled ? "/1.1/statuses/filter.json" : "/1/statuses/filter.json"),
1091+ param,
1092+ ref content,
1093+ userAgent);
10531094 }
10541095
10551096 public void RequestAbort()
--- a/OpenTween/DataModel.cs
+++ b/OpenTween/DataModel.cs
@@ -441,6 +441,27 @@ namespace OpenTween
441441 }
442442
443443 [DataContract]
444+ public class SearchResult11 // API v1.1
445+ {
446+ [DataMember(Name = "statuses")] public List<Status> Statuses;
447+ [DataMember(Name = "search_metadata")] public SearchMetadata11 SearchMetadata;
448+ }
449+
450+ [DataContract]
451+ public class SearchMetadata11 // API v1.1
452+ {
453+ [DataMember(Name = "max_id")] public long MaxId;
454+ [DataMember(Name = "since_id")] public long SinceId;
455+ [DataMember(Name = "refresh_url")] public string RefreshUrl;
456+ [DataMember(Name = "next_results")] public string NextResults;
457+ [DataMember(Name = "count")] public int Count;
458+ [DataMember(Name = "completed_in")] public double CompletedIn;
459+ [DataMember(Name = "since_id_str")] public string SinceIdStr;
460+ [DataMember(Name = "query")] public string Query;
461+ [DataMember(Name = "max_id_str")] public string MaxIdStr;
462+ }
463+
464+ [DataContract]
444465 public class SearchResult
445466 {
446467 [DataMember(Name = "completed_in")] public double CompletedIn;
--- a/OpenTween/MyCommon.cs
+++ b/OpenTween/MyCommon.cs
@@ -680,6 +680,7 @@ namespace OpenTween
680680 }
681681
682682 public static TwitterApiStatus TwitterApiInfo = new TwitterApiStatus();
683+ public static TwitterApiStatus11 TwitterApiInfo11 = new TwitterApiStatus11();
683684
684685 public static bool IsAnimatedGif(string filename)
685686 {
--- a/OpenTween/OpenTween.csproj
+++ b/OpenTween/OpenTween.csproj
@@ -56,6 +56,7 @@
5656 <Compile Include="Api\ApiLimit.cs" />
5757 <Compile Include="Api\TwitterApiAccessLevel.cs" />
5858 <Compile Include="Api\TwitterApiStatus.cs" />
59+ <Compile Include="Api\TwitterApiStatus11.cs" />
5960 <Compile Include="ApplicationEvents.cs">
6061 <SubType>Code</SubType>
6162 </Compile>
--- a/OpenTween/Resources/ChangeLog.txt
+++ b/OpenTween/Resources/ChangeLog.txt
@@ -1,6 +1,10 @@
11 更新履歴
22
33 ==== Ver 1.1.0-beta1(2013/xx/xx)
4+ * 当バージョンから Twitter API v1.1 に対応しています
5+ * API v1.1 の使用に不都合がある場合は、ステータスバーのレートリミット表示をクリックすることで API v1 と切り替えることができます。
6+
7+ * NEW: API v1.1 に対応
48 * NEW: タブの表示位置を画面上部に変更可能に (thx @aokomoriuta!)
59 * NEW: mobile.twitter.com/<スクリーン名>/status/<ステータスID> のURLも関連発言表示の対象に追加
610 * NEW: Favstarなどサードパーティ製サービスのパーマリンクURLも関連発言表示の対象に追加
--- a/OpenTween/ToolStripAPIGauge.cs
+++ b/OpenTween/ToolStripAPIGauge.cs
@@ -40,12 +40,27 @@ namespace OpenTween
4040 public ToolStripAPIGauge()
4141 : base()
4242 {
43- this.Text = "API ???/???";
43+ this.Text = "API v1.1 ???/???";
4444 this.ToolTipText = "API rest ???/???" + Environment.NewLine + "(reset after ??? minutes)";
4545
4646 this.DisplayStyle = ToolStripItemDisplayStyle.Text;
4747 }
4848
49+ [DefaultValue(true)]
50+ [RefreshProperties(RefreshProperties.Repaint)]
51+ public bool API11Enabled
52+ {
53+ get { return this._API11Enabled; }
54+ set
55+ {
56+ this._API11Enabled = value;
57+
58+ this.UpdateText();
59+ this.Invalidate();
60+ }
61+ }
62+ private bool _API11Enabled = true;
63+
4964 /// <summary>
5065 /// ゲージに表示される横棒グラフの幅
5166 /// </summary>
@@ -167,10 +182,16 @@ namespace OpenTween
167182
168183 protected virtual void UpdateText()
169184 {
185+ string apiVersionText;
170186 string remainCountText;
171187 string maxCountText;
172188 string minuteText;
173189
190+ if (this._API11Enabled)
191+ apiVersionText = "v1.1";
192+ else
193+ apiVersionText = "v1";
194+
174195 if (this._ApiLimit == null)
175196 {
176197 remainCountText = "???";
@@ -184,8 +205,8 @@ namespace OpenTween
184205 minuteText = Math.Ceiling(this.remainMinutes).ToString();
185206 }
186207
187- var textFormat = "API {0}/{1}";
188- this.Text = string.Format(textFormat, remainCountText, maxCountText);
208+ var textFormat = "API {0} {1}/{2}";
209+ this.Text = string.Format(textFormat, apiVersionText, remainCountText, maxCountText);
189210
190211 var toolTipTextFormat =
191212 "API rest {0}/{1}" + Environment.NewLine +
--- a/OpenTween/Tween.cs
+++ b/OpenTween/Tween.cs
@@ -555,7 +555,8 @@ namespace OpenTween
555555
556556 SecurityManager = new InternetSecurityManager(PostBrowser);
557557
558- MyCommon.TwitterApiInfo.AccessLimitUpdated += SetStatusLabelApiHandler;
558+ MyCommon.TwitterApiInfo.AccessLimitUpdated += TwitterApiStatus_AccessLimitUpdated;
559+ MyCommon.TwitterApiInfo11.AccessLimitUpdated += TwitterApiStatus_AccessLimitUpdated;
559560 Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
560561
561562 string[] cmdArgs = Environment.GetCommandLineArgs();
@@ -9477,19 +9478,24 @@ namespace OpenTween
94779478 return slbl.ToString();
94789479 }
94799480
9480- delegate void SetStatusLabelApiDelegate();
9481-
9482- private void SetStatusLabelApiHandler(object sender, EventArgs e)
9481+ private void TwitterApiStatus_AccessLimitUpdated(object sender, EventArgs e)
94839482 {
94849483 try
94859484 {
9486- if (InvokeRequired && !IsDisposed)
9485+ if (this.InvokeRequired && !this.IsDisposed)
94879486 {
9488- Invoke(new SetStatusLabelApiDelegate(SetStatusLabelApi));
9487+ this.Invoke((MethodInvoker)(() => this.TwitterApiStatus_AccessLimitUpdated(sender, e)));
94899488 }
94909489 else
94919490 {
9492- SetStatusLabelApi();
9491+ if (sender is TwitterApiStatus11 && this._apiGauge.API11Enabled)
9492+ {
9493+ this._apiGauge.ApiLimit = MyCommon.TwitterApiInfo11.AccessLimit["/statuses/home_timeline"];
9494+ }
9495+ else if (sender is TwitterApiStatus && !this._apiGauge.API11Enabled)
9496+ {
9497+ this._apiGauge.ApiLimit = MyCommon.TwitterApiInfo.AccessLimit;
9498+ }
94939499 }
94949500 }
94959501 catch (ObjectDisposedException)
@@ -9502,11 +9508,6 @@ namespace OpenTween
95029508 }
95039509 }
95049510
9505- private void SetStatusLabelApi()
9506- {
9507- this._apiGauge.ApiLimit = MyCommon.TwitterApiInfo.AccessLimit;
9508- }
9509-
95109511 private void SetStatusLabelUrl()
95119512 {
95129513 StatusLabelUrl.Text = GetStatusLabelText();
@@ -12184,7 +12185,18 @@ namespace OpenTween
1218412185 this.gh.NotifyClicked += GrowlHelper_Callback;
1218512186
1218612187 this._apiGauge = new ToolStripAPIGauge();
12187- this._apiGauge.DoubleClick += this.ApiUsageInfoMenuItem_Click;
12188+ this._apiGauge.Click += (s, e) =>
12189+ {
12190+ var api11Enabled = !HttpTwitter.API11Enabled;
12191+
12192+ HttpTwitter.API11Enabled = api11Enabled;
12193+ (s as ToolStripAPIGauge).API11Enabled = api11Enabled;
12194+
12195+ if (api11Enabled)
12196+ MyCommon.TwitterApiInfo11.Reset();
12197+ else
12198+ MyCommon.TwitterApiInfo.Reset();
12199+ };
1218812200 this.StatusStrip1.Items.Insert(2, this._apiGauge);
1218912201
1219012202 this.ReplaceAppName();
--- a/OpenTween/Twitter.cs
+++ b/OpenTween/Twitter.cs
@@ -170,12 +170,31 @@ namespace OpenTween
170170
171171 //private List<PostClass> _deletemessages = new List<PostClass>();
172172
173+ public TwitterApiAccessLevel AccessLevel
174+ {
175+ get
176+ {
177+ if (HttpTwitter.API11Enabled)
178+ return MyCommon.TwitterApiInfo11.AccessLevel;
179+ else
180+ return MyCommon.TwitterApiInfo.AccessLevel;
181+ }
182+ }
183+
184+ protected void ResetApiStatus()
185+ {
186+ if (HttpTwitter.API11Enabled)
187+ MyCommon.TwitterApiInfo11.Reset();
188+ else
189+ MyCommon.TwitterApiInfo.Reset();
190+ }
191+
173192 public string Authenticate(string username, string password)
174193 {
175194 HttpStatusCode res;
176195 var content = "";
177196
178- MyCommon.TwitterApiInfo.Reset();
197+ this.ResetApiStatus();
179198 try
180199 {
181200 res = twCon.AuthUserAndPass(username, password, ref content);
@@ -227,7 +246,7 @@ namespace OpenTween
227246 //OAuth PIN Flow
228247 bool res;
229248
230- MyCommon.TwitterApiInfo.Reset();
249+ this.ResetApiStatus();
231250 try
232251 {
233252 res = twCon.AuthGetRequestToken(ref pinPageUrl);
@@ -245,7 +264,7 @@ namespace OpenTween
245264 HttpStatusCode res;
246265 var content = "";
247266
248- MyCommon.TwitterApiInfo.Reset();
267+ this.ResetApiStatus();
249268 try
250269 {
251270 res = twCon.AuthGetAccessToken(pinCode);
@@ -295,7 +314,7 @@ namespace OpenTween
295314 public void ClearAuthInfo()
296315 {
297316 Twitter.AccountState = MyCommon.ACCOUNT_STATE.Invalid;
298- MyCommon.TwitterApiInfo.Reset();
317+ this.ResetApiStatus();
299318 twCon.ClearAuthInfo();
300319 }
301320
@@ -366,7 +385,7 @@ namespace OpenTween
366385 {
367386 Twitter.AccountState = MyCommon.ACCOUNT_STATE.Invalid;
368387 }
369- MyCommon.TwitterApiInfo.Reset();
388+ this.ResetApiStatus();
370389 twCon.Initialize(token, tokenSecret, username, userId);
371390 _uname = username.ToLower();
372391 if (AppendSettingDialog.Instance.UserstreamStartup) this.ReconnectUserStream();
@@ -752,7 +771,8 @@ namespace OpenTween
752771 if (MyCommon._endingFlag) return "";
753772
754773 if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
755- if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
774+
775+ if (this.AccessLevel == TwitterApiAccessLevel.Read || this.AccessLevel == TwitterApiAccessLevel.ReadWrite)
756776 {
757777 return "Auth Err:try to re-authorization.";
758778 }
@@ -970,7 +990,8 @@ namespace OpenTween
970990 if (MyCommon._endingFlag) return "";
971991
972992 if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
973- if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
993+
994+ if (this.AccessLevel == TwitterApiAccessLevel.Read || this.AccessLevel == TwitterApiAccessLevel.ReadWrite)
974995 {
975996 return "Auth Err:try to re-authorization.";
976997 }
@@ -2248,6 +2269,56 @@ namespace OpenTween
22482269 return "";
22492270 }
22502271
2272+ // API v1.1
2273+ private string CreatePostsFromSearch11Json(string content, TabClass tab, bool read, int count, ref long minimumId, bool more)
2274+ {
2275+ TwitterDataModel.SearchResult11 items;
2276+ try
2277+ {
2278+ items = MyCommon.CreateDataFromJson<TwitterDataModel.SearchResult11>(content);
2279+ }
2280+ catch (SerializationException ex)
2281+ {
2282+ MyCommon.TraceOut(ex.Message + Environment.NewLine + content);
2283+ return "Json Parse Error(DataContractJsonSerializer)";
2284+ }
2285+ catch (Exception ex)
2286+ {
2287+ MyCommon.TraceOut(ex, MethodBase.GetCurrentMethod().Name + " " + content);
2288+ return "Invalid Json!";
2289+ }
2290+ foreach (var result in items.Statuses)
2291+ {
2292+ PostClass post = null;
2293+ post = CreatePostsFromStatusData(result);
2294+ if (post == null) continue;
2295+
2296+ if (minimumId > post.StatusId) minimumId = post.StatusId;
2297+ if (!more && post.StatusId > tab.SinceId) tab.SinceId = post.StatusId;
2298+ //二重取得回避
2299+ lock (LockObj)
2300+ {
2301+ if (tab == null)
2302+ {
2303+ if (TabInformations.GetInstance().ContainsKey(post.StatusId)) continue;
2304+ }
2305+ else
2306+ {
2307+ if (TabInformations.GetInstance().ContainsKey(post.StatusId, tab.TabName)) continue;
2308+ }
2309+ }
2310+
2311+ post.IsRead = read;
2312+ if ((post.IsMe && !read) && this._readOwnPost) post.IsRead = true;
2313+
2314+ if (tab != null) post.RelTabName = tab.TabName;
2315+ //非同期アイコン取得&StatusDictionaryに追加
2316+ TabInformations.GetInstance().AddPost(post);
2317+ }
2318+
2319+ return "";
2320+ }
2321+
22512322 private string CreatePostsFromSearchJson(string content, TabClass tab, bool read, int count, ref long minimumId, bool more)
22522323 {
22532324 TwitterDataModel.SearchResult items;
@@ -2715,7 +2786,10 @@ namespace OpenTween
27152786
27162787 if (!TabInformations.GetInstance().ContainsTab(tab)) return "";
27172788
2718- return this.CreatePostsFromSearchJson(content, tab, read, count, ref tab.OldestId, more);
2789+ if (HttpTwitter.API11Enabled)
2790+ return this.CreatePostsFromSearch11Json(content, tab, read, count, ref tab.OldestId, more);
2791+ else
2792+ return this.CreatePostsFromSearchJson(content, tab, read, count, ref tab.OldestId, more);
27192793 }
27202794
27212795 public string GetPhoenixSearch(bool read,
@@ -2918,7 +2992,8 @@ namespace OpenTween
29182992 if (MyCommon._endingFlag) return "";
29192993
29202994 if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return "";
2921- if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.Read || MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
2995+
2996+ if (this.AccessLevel == TwitterApiAccessLevel.Read || this.AccessLevel == TwitterApiAccessLevel.ReadWrite)
29222997 {
29232998 return "Auth Err:try to re-authorization.";
29242999 }
@@ -4088,7 +4163,7 @@ namespace OpenTween
40884163 }
40894164 catch(Exception)
40904165 {
4091- MyCommon.TwitterApiInfo.Reset();
4166+ this.ResetApiStatus();
40924167 return false;
40934168 }
40944169