OSDN Git Service

Twitterへの複数画像の投稿に対応した
[opentween/open-tween.git] / OpenTween / Connection / HttpTwitter.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 //           (c) 2008-2011 Moz (@syo68k)
4 //           (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 //           (c) 2011      kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
8 // All rights reserved.
9 // 
10 // This file is part of OpenTween.
11 // 
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
15 // any later version.
16 // 
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
20 // for more details. 
21 // 
22 // You should have received a copy of the GNU General public License along
23 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
26
27 using System;
28 using System.Collections.Generic;
29 using System.Linq;
30 using System.Text;
31 using System.Net;
32 using System.IO;
33
34 namespace OpenTween
35 {
36     public class HttpTwitter : ICloneable
37     {
38         //OAuth関連
39         ///<summary>
40         ///OAuthのアクセストークン取得先URI
41         ///</summary>
42         private const string AccessTokenUrlXAuth = "https://api.twitter.com/oauth/access_token";
43         private const string RequestTokenUrl = "https://api.twitter.com/oauth/request_token";
44         private const string AuthorizeUrl = "https://api.twitter.com/oauth/authorize";
45         private const string AccessTokenUrl = "https://api.twitter.com/oauth/access_token";
46
47         private const string PostMethod = "POST";
48         private const string GetMethod = "GET";
49
50         private IHttpConnection httpCon; //HttpConnectionApi or HttpConnectionOAuth
51         private HttpVarious httpConVar = new HttpVarious();
52
53         private enum AuthMethod
54         {
55             OAuth,
56             Basic,
57         }
58         private AuthMethod connectionType = AuthMethod.Basic;
59
60         private string requestToken;
61
62         private static string tk = "";
63         private static string tks = "";
64         private static string un = "";
65
66         public void Initialize(string accessToken,
67                                         string accessTokenSecret,
68                                         string username,
69                                         long userId)
70         {
71             //for OAuth
72             HttpOAuthApiProxy con = new HttpOAuthApiProxy();
73             if (tk != accessToken || tks != accessTokenSecret ||
74                     un != username || connectionType != AuthMethod.OAuth)
75             {
76                 // 以前の認証状態よりひとつでも変化があったらhttpヘッダより読み取ったカウントは初期化
77                 tk = accessToken;
78                 tks = accessTokenSecret;
79                 un = username;
80             }
81             con.Initialize(ApplicationSettings.TwitterConsumerKey, ApplicationSettings.TwitterConsumerSecret, accessToken, accessTokenSecret, username, userId, "screen_name", "user_id");
82             httpCon = con;
83             connectionType = AuthMethod.OAuth;
84             requestToken = "";
85         }
86
87         public string AccessToken
88         {
89             get
90             {
91                 if (httpCon != null)
92                     return ((HttpConnectionOAuth)httpCon).AccessToken;
93                 else
94                     return "";
95             }
96         }
97
98         public string AccessTokenSecret
99         {
100             get
101             {
102                 if (httpCon != null)
103                     return ((HttpConnectionOAuth)httpCon).AccessTokenSecret;
104                 else
105                     return "";
106             }
107         }
108
109         public string AuthenticatedUsername
110         {
111             get
112             {
113                 if (httpCon != null)
114                     return httpCon.AuthUsername;
115                 else
116                     return "";
117             }
118         }
119
120         public long AuthenticatedUserId
121         {
122             get
123             {
124                 if (httpCon != null)
125                     return httpCon.AuthUserId;
126                 else
127                     return 0;
128             }
129             set
130             {
131                 if (httpCon != null)
132                     httpCon.AuthUserId = value;
133             }
134         }
135
136         public string Password
137         {
138             get
139             {
140                 return "";
141             }
142         }
143
144         public bool AuthGetRequestToken(ref string content)
145         {
146             Uri authUri = null;
147             bool result = ((HttpOAuthApiProxy)httpCon).AuthenticatePinFlowRequest(RequestTokenUrl, AuthorizeUrl, ref requestToken, ref authUri);
148             content = authUri.ToString();
149             return result;
150         }
151
152         public HttpStatusCode AuthGetAccessToken(string pin)
153         {
154             return ((HttpOAuthApiProxy)httpCon).AuthenticatePinFlow(AccessTokenUrl, requestToken, pin);
155         }
156
157         public HttpStatusCode AuthUserAndPass(string username, string password, ref string content)
158         {
159             return httpCon.Authenticate(new Uri(AccessTokenUrlXAuth), username, password, ref content);
160         }
161
162         public void ClearAuthInfo()
163         {
164             this.Initialize("", "", "", 0);
165         }
166
167         public HttpStatusCode UpdateStatus(string status, long? replyToId, List<long> mediaIds, ref string content)
168         {
169             Dictionary<string, string> param = new Dictionary<string, string>();
170             param.Add("status", status);
171             if (replyToId != null) param.Add("in_reply_to_status_id", replyToId.ToString());
172             param.Add("include_entities", "true");
173             //if (AppendSettingDialog.Instance.ShortenTco && AppendSettingDialog.Instance.UrlConvertAuto) param.Add("wrap_links", "true")
174
175             if (mediaIds != null)
176             {
177                 StringBuilder sb = new StringBuilder();
178                 foreach (var idStr in mediaIds.Select(x => x.ToString()))
179                 {
180                     if (string.IsNullOrEmpty(idStr)) continue;
181                     if (sb.Length > 0) sb.Append(",");
182                     sb.Append(idStr);
183                 }
184
185                 if (sb.Length > 0) param.Add("media_ids", sb.ToString());
186             }
187
188             return httpCon.GetContent(PostMethod,
189                 this.CreateTwitterUri("/1.1/statuses/update.json"),
190                 param,
191                 ref content,
192                 null,
193                 null);
194         }
195
196         public HttpStatusCode UpdateStatusWithMedia(string status, long? replyToId, FileInfo mediaFile, ref string content)
197         {
198             //画像投稿用エンドポイント
199             Dictionary<string, string> param = new Dictionary<string, string>();
200             param.Add("status", status);
201             if (replyToId != null) param.Add("in_reply_to_status_id", replyToId.ToString());
202             param.Add("include_entities", "true");
203             //if (AppendSettingDialog.Instance.ShortenTco && AppendSettingDialog.Instance.UrlConvertAuto) param.Add("wrap_links", "true")
204
205             List<KeyValuePair<string, FileInfo>> binary = new List<KeyValuePair<string, FileInfo>>();
206             binary.Add(new KeyValuePair<string, FileInfo>("media[]", mediaFile));
207
208             return httpCon.GetContent(PostMethod,
209                 this.CreateTwitterUri("/1.1/statuses/update_with_media.json"),
210                 param,
211                 binary,
212                 ref content,
213                 this.CreateRatelimitHeadersDict(),
214                 this.CreateApiCalllback("/statuses/update_with_media"));
215         }
216
217         public HttpStatusCode UploadMedia(FileInfo mediaFile, ref string content)
218         {
219             //画像投稿専用エンドポイント
220             List<KeyValuePair<string, FileInfo>> binary = new List<KeyValuePair<string, FileInfo>>();
221             binary.Add(new KeyValuePair<string, FileInfo>("media", mediaFile));
222
223             return httpCon.GetContent(PostMethod,
224                 this.CreateTwitterUploadUri("/1.1/media/upload.json"),
225                 null,
226                 binary,
227                 ref content,
228                 null,
229                 null);
230         }
231
232         public HttpStatusCode DestroyStatus(long id)
233         {
234             string content = null;
235
236             return httpCon.GetContent(PostMethod,
237                 this.CreateTwitterUri("/1.1/statuses/destroy/" + id + ".json"),
238                 null,
239                 ref content,
240                 null,
241                 null);
242         }
243
244         public HttpStatusCode SendDirectMessage(string status, string sendto, ref string content)
245         {
246             Dictionary<string, string> param = new Dictionary<string, string>();
247             param.Add("text", status);
248             param.Add("screen_name", sendto);
249             //if (AppendSettingDialog.Instance.ShortenTco && AppendSettingDialog.Instance.UrlConvertAuto) param.Add("wrap_links", "true")
250
251             return httpCon.GetContent(PostMethod,
252                 this.CreateTwitterUri("/1.1/direct_messages/new.json"),
253                 param,
254                 ref content,
255                 null,
256                 null);
257         }
258
259         public HttpStatusCode DestroyDirectMessage(long id)
260         {
261             string content = null;
262
263             var param = new Dictionary<string, string>();
264             param.Add("id", id.ToString());
265
266             return httpCon.GetContent(PostMethod,
267                 this.CreateTwitterUri("/1.1/direct_messages/destroy.json"),
268                 param,
269                 ref content,
270                 null,
271                 null);
272         }
273
274         public HttpStatusCode RetweetStatus(long id, ref string content)
275         {
276             Dictionary<string, string> param = new Dictionary<string, string>();
277             param.Add("include_entities", "true");
278
279             return httpCon.GetContent(PostMethod,
280                 this.CreateTwitterUri("/1.1/statuses/retweet/" + id + ".json"),
281                 param,
282                 ref content,
283                 null,
284                 null);
285         }
286
287         public HttpStatusCode ShowUserInfo(string screenName, ref string content)
288         {
289             Dictionary<string, string> param = new Dictionary<string, string>();
290             param.Add("screen_name", screenName);
291             param.Add("include_entities", "true");
292             return httpCon.GetContent(GetMethod,
293                 this.CreateTwitterUri("/1.1/users/show.json"),
294                 param,
295                 ref content,
296                 this.CreateRatelimitHeadersDict(),
297                 this.CreateApiCalllback("/users/show/:id"));
298         }
299
300         public HttpStatusCode CreateFriendships(string screenName, ref string content)
301         {
302             Dictionary<string, string> param = new Dictionary<string, string>();
303             param.Add("screen_name", screenName);
304
305             return httpCon.GetContent(PostMethod,
306                 this.CreateTwitterUri("/1.1/friendships/create.json"),
307                 param,
308                 ref content,
309                 null,
310                 null);
311         }
312
313         public HttpStatusCode DestroyFriendships(string screenName, ref string content)
314         {
315             Dictionary<string, string> param = new Dictionary<string, string>();
316             param.Add("screen_name", screenName);
317
318             return httpCon.GetContent(PostMethod,
319                 this.CreateTwitterUri("/1.1/friendships/destroy.json"),
320                 param,
321                 ref content,
322                 null,
323                 null);
324         }
325
326         public HttpStatusCode CreateBlock(string screenName, ref string content)
327         {
328             Dictionary<string, string> param = new Dictionary<string, string>();
329             param.Add("screen_name", screenName);
330
331             return httpCon.GetContent(PostMethod,
332                 this.CreateTwitterUri("/1.1/blocks/create.json"),
333                 param,
334                 ref content,
335                 null,
336                 null);
337         }
338
339         public HttpStatusCode DestroyBlock(string screenName, ref string content)
340         {
341             Dictionary<string, string> param = new Dictionary<string, string>();
342             param.Add("screen_name", screenName);
343
344             return httpCon.GetContent(PostMethod,
345                 this.CreateTwitterUri("/1.1/blocks/destroy.json"),
346                 param,
347                 ref content,
348                 null,
349                 null);
350         }
351
352         public HttpStatusCode ReportSpam(string screenName, ref string content)
353         {
354             Dictionary<string, string> param = new Dictionary<string, string>();
355             param.Add("screen_name", screenName);
356
357             return httpCon.GetContent(PostMethod,
358                 this.CreateTwitterUri("/1.1/users/report_spam.json"),
359                 param,
360                 ref content,
361                 null,
362                 null);
363         }
364
365         public HttpStatusCode ShowFriendships(string souceScreenName, string targetScreenName, ref string content)
366         {
367             Dictionary<string, string> param = new Dictionary<string, string>();
368             param.Add("source_screen_name", souceScreenName);
369             param.Add("target_screen_name", targetScreenName);
370
371             return httpCon.GetContent(GetMethod,
372                 this.CreateTwitterUri("/1.1/friendships/show.json"),
373                 param,
374                 ref content,
375                 this.CreateRatelimitHeadersDict(),
376                 this.CreateApiCalllback("/friendships/show"));
377         }
378
379         public HttpStatusCode ShowStatuses(long id, ref string content)
380         {
381             Dictionary<string, string> param = new Dictionary<string, string>();
382             param.Add("include_entities", "true");
383             return httpCon.GetContent(GetMethod,
384                 this.CreateTwitterUri("/1.1/statuses/show/" + id + ".json"),
385                 param,
386                 ref content,
387                 this.CreateRatelimitHeadersDict(),
388                 this.CreateApiCalllback("/statuses/show/:id"));
389         }
390
391         public HttpStatusCode CreateFavorites(long id, ref string content)
392         {
393             var param = new Dictionary<string, string>();
394             param.Add("id", id.ToString());
395
396             return httpCon.GetContent(PostMethod,
397                 this.CreateTwitterUri("/1.1/favorites/create.json"),
398                 param,
399                 ref content,
400                 null,
401                 null);
402         }
403
404         public HttpStatusCode DestroyFavorites(long id, ref string content)
405         {
406             var param = new Dictionary<string, string>();
407             param.Add("id", id.ToString());
408
409             return httpCon.GetContent(PostMethod,
410                 this.CreateTwitterUri("/1.1/favorites/destroy.json"),
411                 param,
412                 ref content,
413                 null,
414                 null);
415         }
416
417         public HttpStatusCode HomeTimeline(int? count, long? max_id, long? since_id, ref string content)
418         {
419             Dictionary<string, string> param = new Dictionary<string, string>();
420             if (count != null)
421                 param.Add("count", count.ToString());
422             if (max_id != null)
423                 param.Add("max_id", max_id.ToString());
424             if (since_id != null)
425                 param.Add("since_id", since_id.ToString());
426
427             param.Add("include_entities", "true");
428
429             return httpCon.GetContent(GetMethod,
430                 this.CreateTwitterUri("/1.1/statuses/home_timeline.json"),
431                 param,
432                 ref content,
433                 this.CreateRatelimitHeadersDict(),
434                 this.CreateApiCalllback("/statuses/home_timeline"));
435         }
436
437         public HttpStatusCode UserTimeline(long? user_id, string screen_name, int? count, long? max_id, long? since_id, ref string content)
438         {
439             Dictionary<string, string> param = new Dictionary<string, string>();
440
441             if ((user_id == null && string.IsNullOrEmpty(screen_name)) ||
442                 (user_id != null && !string.IsNullOrEmpty(screen_name))) return HttpStatusCode.BadRequest;
443
444             if (user_id != null)
445                 param.Add("user_id", user_id.ToString());
446             if (!string.IsNullOrEmpty(screen_name))
447                 param.Add("screen_name", screen_name);
448             if (count != null)
449                 param.Add("count", count.ToString());
450             if (max_id != null)
451                 param.Add("max_id", max_id.ToString());
452             if (since_id != null)
453                 param.Add("since_id", since_id.ToString());
454
455             param.Add("include_rts", "true");
456             param.Add("include_entities", "true");
457
458             return httpCon.GetContent(GetMethod,
459                 this.CreateTwitterUri("/1.1/statuses/user_timeline.json"),
460                 param,
461                 ref content,
462                 this.CreateRatelimitHeadersDict(),
463                 this.CreateApiCalllback("/statuses/user_timeline"));
464         }
465
466         public HttpStatusCode Mentions(int? count, long? max_id, long? since_id, ref string content)
467         {
468             Dictionary<string, string> param = new Dictionary<string, string>();
469             if (count != null)
470                 param.Add("count", count.ToString());
471             if (max_id != null)
472                 param.Add("max_id", max_id.ToString());
473             if (since_id != null)
474                 param.Add("since_id", since_id.ToString());
475
476             param.Add("include_entities", "true");
477
478             return httpCon.GetContent(GetMethod,
479                 this.CreateTwitterUri("/1.1/statuses/mentions_timeline.json"),
480                 param,
481                 ref content,
482                 this.CreateRatelimitHeadersDict(),
483                 this.CreateApiCalllback("/statuses/mentions_timeline"));
484         }
485
486         public HttpStatusCode DirectMessages(int? count, long? max_id, long? since_id, ref string content)
487         {
488             Dictionary<string, string> param = new Dictionary<string, string>();
489             if (count != null)
490                 param.Add("count", count.ToString());
491             if (max_id != null)
492                 param.Add("max_id", max_id.ToString());
493             if (since_id != null)
494                 param.Add("since_id", since_id.ToString());
495             param.Add("include_entities", "true");
496
497             return httpCon.GetContent(GetMethod,
498                 this.CreateTwitterUri("/1.1/direct_messages.json"),
499                 param,
500                 ref content,
501                 this.CreateRatelimitHeadersDict(),
502                 this.CreateApiCalllback("/direct_messages"));
503         }
504
505         public HttpStatusCode DirectMessagesSent(int? count, long? max_id, long? since_id, ref string content)
506         {
507             Dictionary<string, string> param = new Dictionary<string, string>();
508             if (count != null)
509                 param.Add("count", count.ToString());
510             if (max_id != null)
511                 param.Add("max_id", max_id.ToString());
512             if (since_id != null)
513                 param.Add("since_id", since_id.ToString());
514             param.Add("include_entities", "true");
515
516             return httpCon.GetContent(GetMethod,
517                 this.CreateTwitterUri("/1.1/direct_messages/sent.json"),
518                 param,
519                 ref content,
520                 this.CreateRatelimitHeadersDict(),
521                 this.CreateApiCalllback("/direct_messages/sent"));
522         }
523
524         public HttpStatusCode Favorites(int? count, int? page, ref string content)
525         {
526             Dictionary<string, string> param = new Dictionary<string, string>();
527             if (count != null) param.Add("count", count.ToString());
528
529             if (page != null)
530             {
531                 param.Add("page", page.ToString());
532             }
533
534             param.Add("include_entities", "true");
535
536             return httpCon.GetContent(GetMethod,
537                 this.CreateTwitterUri("/1.1/favorites/list.json"),
538                 param,
539                 ref content,
540                 this.CreateRatelimitHeadersDict(),
541                 this.CreateApiCalllback("/favorites/list"));
542         }
543
544         public HttpStatusCode Search(string words, string lang, int? count, long? maxId, long? sinceId, ref string content)
545         {
546             Dictionary<string, string> param = new Dictionary<string, string>();
547             if (!string.IsNullOrEmpty(words)) param.Add("q", words);
548             if (!string.IsNullOrEmpty(lang)) param.Add("lang", lang);
549             if (count != null) param.Add("count", count.ToString());
550             if (maxId != null) param.Add("max_id", maxId.ToString());
551             if (sinceId != null) param.Add("since_id", sinceId.ToString());
552
553             if (param.Count == 0) return HttpStatusCode.BadRequest;
554
555             param.Add("result_type", "recent");
556             param.Add("include_entities", "true");
557             return httpCon.GetContent(GetMethod,
558                 this.CreateTwitterUri("/1.1/search/tweets.json"),
559                 param,
560                 ref content,
561                 this.CreateRatelimitHeadersDict(),
562                 this.CreateApiCalllback("/search/tweets"));
563         }
564
565         public HttpStatusCode SavedSearches(ref string content)
566         {
567             return httpCon.GetContent(GetMethod,
568                 this.CreateTwitterUri("/1.1/saved_searches/list.json"),
569                 null,
570                 ref content,
571                 this.CreateRatelimitHeadersDict(),
572                 this.CreateApiCalllback("/saved_searches/list"));
573         }
574
575         public HttpStatusCode FollowerIds(long cursor, ref string content)
576         {
577             Dictionary<string, string> param = new Dictionary<string, string>();
578             param.Add("cursor", cursor.ToString());
579
580             return httpCon.GetContent(GetMethod,
581                 this.CreateTwitterUri("/1.1/followers/ids.json"),
582                 param,
583                 ref content,
584                 this.CreateRatelimitHeadersDict(),
585                 this.CreateApiCalllback("/followers/ids"));
586         }
587
588         public HttpStatusCode NoRetweetIds(ref string content)
589         {
590             return httpCon.GetContent(GetMethod,
591                 this.CreateTwitterUri("/1.1/friendships/no_retweets/ids.json"),
592                 null,
593                 ref content,
594                 this.CreateRatelimitHeadersDict(),
595                 this.CreateApiCalllback("/friendships/no_retweets/ids"));
596         }
597
598         public HttpStatusCode RateLimitStatus(ref string content)
599         {
600             return httpCon.GetContent(GetMethod,
601                 this.CreateTwitterUri("/1.1/application/rate_limit_status.json"),
602                 null,
603                 ref content,
604                 this.CreateRatelimitHeadersDict(),
605                 this.CreateApiCalllback("/application/rate_limit_status"));
606         }
607
608         #region Lists
609         public HttpStatusCode GetLists(string user, ref string content)
610         {
611             Dictionary<string, string> param = new Dictionary<string, string>();
612             param.Add("screen_name", user);
613
614             return httpCon.GetContent(GetMethod,
615                 this.CreateTwitterUri("/1.1/lists/list.json"),
616                 param,
617                 ref content,
618                 this.CreateRatelimitHeadersDict(),
619                 this.CreateApiCalllback("/lists/list"));
620         }
621
622         public HttpStatusCode UpdateListID(string user, string list_id, string name, Boolean isPrivate, string description, ref string content)
623         {
624             string mode = "public";
625             if (isPrivate)
626                 mode = "private";
627
628             Dictionary<string, string> param = new Dictionary<string, string>();
629             param.Add("screen_name", user);
630             param.Add("list_id", list_id);
631             if (name != null) param.Add("name", name);
632             if (mode != null) param.Add("mode", mode);
633             if (description != null) param.Add("description", description);
634
635             return httpCon.GetContent(PostMethod,
636                 this.CreateTwitterUri("/1.1/lists/update.json"),
637                 param,
638                 ref content,
639                 null,
640                 null);
641         }
642
643         public HttpStatusCode DeleteListID(string user, string list_id, ref string content)
644         {
645             Dictionary<string, string> param = new Dictionary<string, string>();
646             param.Add("screen_name", user);
647             param.Add("list_id", list_id);
648
649             return httpCon.GetContent(PostMethod,
650                 this.CreateTwitterUri("/1.1/lists/destroy.json"),
651                 param,
652                 ref content,
653                 null,
654                 null);
655         }
656
657         public HttpStatusCode GetListsSubscriptions(string user, ref string content)
658         {
659             Dictionary<string, string> param = new Dictionary<string, string>();
660             param.Add("screen_name", user);
661
662             return httpCon.GetContent(GetMethod,
663                 this.CreateTwitterUri("/1.1/lists/subscriptions.json"),
664                 param,
665                 ref content,
666                 this.CreateRatelimitHeadersDict(),
667                 this.CreateApiCalllback("/lists/subscriptions"));
668         }
669
670         public HttpStatusCode GetListsStatuses(long userId, long list_id, int? per_page, long? max_id, long? since_id, Boolean isRTinclude, ref string content)
671         {
672             //認証なくても取得できるが、protectedユーザー分が抜ける
673             Dictionary<string, string> param = new Dictionary<string, string>();
674             param.Add("user_id", userId.ToString());
675             param.Add("list_id", list_id.ToString());
676             param.Add("include_rts", isRTinclude ? "true" : "false");
677             if (per_page != null)
678                 param.Add("count", per_page.ToString());
679             if (max_id != null)
680                 param.Add("max_id", max_id.ToString());
681             if (since_id != null)
682                 param.Add("since_id", since_id.ToString());
683             param.Add("include_entities", "true");
684
685             return httpCon.GetContent(GetMethod,
686                 this.CreateTwitterUri("/1.1/lists/statuses.json"),
687                 param,
688                 ref content,
689                 this.CreateRatelimitHeadersDict(),
690                 this.CreateApiCalllback("/lists/statuses"));
691         }
692
693         public HttpStatusCode CreateLists(string listname, Boolean isPrivate, string description, ref string content)
694         {
695             string mode = "public";
696             if (isPrivate)
697                 mode = "private";
698
699             Dictionary<string, string> param = new Dictionary<string, string>();
700             param.Add("name", listname);
701             param.Add("mode", mode);
702             if (!string.IsNullOrEmpty(description))
703                 param.Add("description", description);
704
705             return httpCon.GetContent(PostMethod,
706                 this.CreateTwitterUri("/1.1/lists/create.json"),
707                 param,
708                 ref content,
709                 null,
710                 null);
711         }
712
713         public HttpStatusCode GetListMembers(string user, string list_id, long cursor, ref string content)
714         {
715             Dictionary<string, string> param = new Dictionary<string, string>();
716             param.Add("screen_name", user);
717             param.Add("list_id", list_id);
718             param.Add("cursor", cursor.ToString());
719             return httpCon.GetContent(GetMethod,
720                 this.CreateTwitterUri("/1.1/lists/members.json"),
721                 param,
722                 ref content,
723                 this.CreateRatelimitHeadersDict(),
724                 this.CreateApiCalllback("/lists/members"));
725         }
726
727         public HttpStatusCode CreateListMembers(string list_id, string memberName, ref string content)
728         {
729             Dictionary<string, string> param = new Dictionary<string, string>();
730             param.Add("list_id", list_id);
731             param.Add("screen_name", memberName);
732             return httpCon.GetContent(PostMethod,
733                 this.CreateTwitterUri("/1.1/lists/members/create.json"),
734                 param,
735                 ref content,
736                 null,
737                 null);
738         }
739
740         public HttpStatusCode DeleteListMembers(string list_id, string memberName, ref string content)
741         {
742             Dictionary<string, string> param = new Dictionary<string, string>();
743             param.Add("screen_name", memberName);
744             param.Add("list_id", list_id);
745             return httpCon.GetContent(PostMethod,
746                 this.CreateTwitterUri("/1.1/lists/members/destroy.json"),
747                 param,
748                 ref content,
749                 null,
750                 null);
751         }
752
753         public HttpStatusCode ShowListMember(string list_id, string memberName, ref string content)
754         {
755             Dictionary<string, string> param = new Dictionary<string, string>();
756             param.Add("screen_name", memberName);
757             param.Add("list_id", list_id);
758             return httpCon.GetContent(GetMethod,
759                 this.CreateTwitterUri("/1.1/lists/members/show.json"),
760                 param,
761                 ref content,
762                 this.CreateRatelimitHeadersDict(),
763                 this.CreateApiCalllback("/lists/members/show"));
764         }
765         #endregion
766
767         public HttpStatusCode Statusid_retweeted_by_ids(long statusid, int? count, int? page, ref string content)
768         {
769             Dictionary<string, string> param = new Dictionary<string, string>();
770             if (count != null)
771                 param.Add("count", count.ToString());
772             if (page != null)
773                 param.Add("page", page.ToString());
774
775             param.Add("id", statusid.ToString());
776
777             return httpCon.GetContent(GetMethod,
778                 this.CreateTwitterUri("/1.1/statuses/retweeters/ids.json"),
779                 param,
780                 ref content,
781                 this.CreateRatelimitHeadersDict(),
782                 this.CreateApiCalllback("/statuses/retweeters/ids"));
783         }
784
785         public HttpStatusCode UpdateProfile(string name, string url, string location, string description, ref string content)
786         {
787             Dictionary<string, string> param = new Dictionary<string, string>();
788
789             param.Add("name", WebUtility.HtmlEncode(name));
790             param.Add("url", url);
791             param.Add("location", WebUtility.HtmlEncode(location));
792             param.Add("description", WebUtility.HtmlEncode(description));
793             param.Add("include_entities", "true");
794
795             return httpCon.GetContent(PostMethod,
796                 this.CreateTwitterUri("/1.1/account/update_profile.json"),
797                 param,
798                 ref content,
799                 null,
800                 null);
801         }
802
803         public HttpStatusCode UpdateProfileImage(FileInfo imageFile, ref string content)
804         {
805             List<KeyValuePair<string, FileInfo>> binary = new List<KeyValuePair<string, FileInfo>>();
806             binary.Add(new KeyValuePair<string, FileInfo>("image", imageFile));
807
808             return httpCon.GetContent(PostMethod,
809                 this.CreateTwitterUri("/1.1/account/update_profile_image.json"),
810                 null,
811                 binary,
812                 ref content,
813                 null,
814                 null);
815         }
816
817         public HttpStatusCode GetBlockUserIds(ref string content, long? cursor)
818         {
819             var param = new Dictionary<string, string>();
820
821             if (cursor != null)
822                 param.Add("cursor", cursor.ToString());
823
824             return httpCon.GetContent(GetMethod,
825                 this.CreateTwitterUri("/1.1/blocks/ids.json"),
826                 param,
827                 ref content,
828                 this.CreateRatelimitHeadersDict(),
829                 this.CreateApiCalllback("/blocks/ids"));
830         }
831
832         public HttpStatusCode GetMuteUserIds(ref string content, long? cursor)
833         {
834             var param = new Dictionary<string, string>();
835
836             if (cursor != null)
837                 param.Add("cursor", cursor.ToString());
838
839             return httpCon.GetContent(GetMethod,
840                 this.CreateTwitterUri("/1.1/mutes/users/ids.json"),
841                 param,
842                 ref content,
843                 this.CreateRatelimitHeadersDict(),
844                 this.CreateApiCalllback("/1.1/mutes/users/ids"));
845         }
846
847         public HttpStatusCode GetConfiguration(ref string content)
848         {
849             return httpCon.GetContent(GetMethod,
850                 this.CreateTwitterUri("/1.1/help/configuration.json"),
851                 null,
852                 ref content,
853                 this.CreateRatelimitHeadersDict(),
854                 this.CreateApiCalllback("/help/configuration"));
855         }
856
857         public HttpStatusCode VerifyCredentials(ref string content)
858         {
859             return httpCon.GetContent(GetMethod,
860                 this.CreateTwitterUri("/1.1/account/verify_credentials.json"),
861                 null,
862                 ref content,
863                 this.CreateRatelimitHeadersDict(),
864                 this.CreateApiCalllback("/account/verify_credentials"));
865         }
866
867         #region Proxy API
868         private static string _twitterUrl = "api.twitter.com";
869         private static string _twitterUserStreamUrl = "userstream.twitter.com";
870         private static string _twitterStreamUrl = "stream.twitter.com";
871         private static string _twitterUploadUrl = "upload.twitter.com";
872
873         private Uri CreateTwitterUri(string path)
874         {
875             return new Uri(string.Format("{0}{1}{2}", "https://", _twitterUrl, path));
876         }
877
878         private Uri CreateTwitterUserStreamUri(string path)
879         {
880             return new Uri(string.Format("{0}{1}{2}", "https://", _twitterUserStreamUrl, path));
881         }
882
883         private Uri CreateTwitterStreamUri(string path)
884         {
885             return new Uri(string.Format("{0}{1}{2}", "http://", _twitterStreamUrl, path));
886         }
887
888         private Uri CreateTwitterUploadUri(string path)
889         {
890             return new Uri(string.Format("{0}{1}{2}", "https://", _twitterUploadUrl, path));
891         }
892
893         public static string TwitterUrl
894         {
895             set
896             {
897                 _twitterUrl = value;
898                 HttpOAuthApiProxy.ProxyHost = value;
899             }
900         }
901         #endregion
902
903         private Dictionary<string, string> CreateRatelimitHeadersDict()
904         {
905             return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
906             {
907                 {"X-Access-Level", ""},
908                 {"X-RateLimit-Limit", ""},
909                 {"X-RateLimit-Remaining", ""},
910                 {"X-RateLimit-Reset", ""},
911                 {"X-Rate-Limit-Limit", ""},
912                 {"X-Rate-Limit-Remaining", ""},
913                 {"X-Rate-Limit-Reset", ""},
914                 {"X-MediaRateLimit-Limit", ""},
915                 {"X-MediaRateLimit-Remaining", ""},
916                 {"X-MediaRateLimit-Reset", ""},
917             };
918         }
919
920         private CallbackDelegate CreateApiCalllback(string endpointName)
921         {
922             return (sender, code, headerInfo, content) =>
923             {
924                 if (code < HttpStatusCode.InternalServerError)
925                     MyCommon.TwitterApiInfo.UpdateFromHeader(headerInfo, endpointName);
926             };
927         }
928
929         public HttpStatusCode UserStream(ref Stream content,
930                                          bool allAtReplies,
931                                          string trackwords,
932                                          string userAgent)
933         {
934             Dictionary<string, string> param = new Dictionary<string, string>();
935
936             if (allAtReplies)
937                 param.Add("replies", "all");
938
939             if (!string.IsNullOrEmpty(trackwords))
940                 param.Add("track", trackwords);
941
942             return httpCon.GetContent(GetMethod,
943                 this.CreateTwitterUserStreamUri("/1.1/user.json"),
944                 param,
945                 ref content,
946                 userAgent);
947         }
948
949         public HttpStatusCode FilterStream(ref Stream content,
950                                            string trackwords,
951                                            string userAgent)
952         {
953             //文中の日本語キーワードに反応せず、使えない(スペースで分かち書きしてないと反応しない)
954             Dictionary<string, string> param = new Dictionary<string, string>();
955
956             if (!string.IsNullOrEmpty(trackwords))
957                 param.Add("track", string.Join(",", trackwords.Split(" ".ToCharArray())));
958
959             return httpCon.GetContent(PostMethod,
960                 this.CreateTwitterStreamUri("/1.1/statuses/filter.json"),
961                 param,
962                 ref content,
963                 userAgent);
964         }
965
966         public void RequestAbort()
967         {
968             httpCon.RequestAbort();
969         }
970
971         public object Clone()
972         {
973             HttpTwitter myCopy = new HttpTwitter();
974             myCopy.Initialize(this.AccessToken, this.AccessTokenSecret, this.AuthenticatedUsername, this.AuthenticatedUserId);
975             return myCopy;
976         }
977     }
978 }