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.
10 // This file is part of OpenTween.
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)
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
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.
28 using System.Collections.Generic;
36 public class HttpTwitter : ICloneable
40 ///OAuthのアクセストークン取得先URI
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";
47 private const string PostMethod = "POST";
48 private const string GetMethod = "GET";
50 private IHttpConnection httpCon; //HttpConnectionApi or HttpConnectionOAuth
52 private enum AuthMethod
57 private AuthMethod connectionType = AuthMethod.Basic;
59 private string requestToken;
61 private static string tk = "";
62 private static string tks = "";
63 private static string un = "";
65 public void Initialize(string accessToken,
66 string accessTokenSecret,
71 HttpOAuthApiProxy con = new HttpOAuthApiProxy();
72 if (tk != accessToken || tks != accessTokenSecret ||
73 un != username || connectionType != AuthMethod.OAuth)
75 // 以前の認証状態よりひとつでも変化があったらhttpヘッダより読み取ったカウントは初期化
77 tks = accessTokenSecret;
80 con.Initialize(ApplicationSettings.TwitterConsumerKey, ApplicationSettings.TwitterConsumerSecret, accessToken, accessTokenSecret, username, userId, "screen_name", "user_id");
81 con.CacheEnabled = false;
83 connectionType = AuthMethod.OAuth;
87 public string AccessToken
91 return ((HttpConnectionOAuth)httpCon)?.AccessToken ?? "";
95 public string AccessTokenSecret
99 return ((HttpConnectionOAuth)httpCon)?.AccessTokenSecret ?? "";
103 public string AuthenticatedUsername
107 return httpCon?.AuthUsername ?? "";
111 public long AuthenticatedUserId
115 return httpCon?.AuthUserId ?? 0;
120 httpCon.AuthUserId = value;
124 public string Password
132 public bool AuthGetRequestToken(ref string content)
135 bool result = ((HttpOAuthApiProxy)httpCon).AuthenticatePinFlowRequest(RequestTokenUrl, AuthorizeUrl, ref requestToken, ref authUri);
136 content = authUri.AbsoluteUri;
140 public HttpStatusCode AuthGetAccessToken(string pin)
142 return ((HttpOAuthApiProxy)httpCon).AuthenticatePinFlow(AccessTokenUrl, requestToken, pin);
145 public HttpStatusCode AuthUserAndPass(string username, string password, ref string content)
147 return httpCon.Authenticate(new Uri(AccessTokenUrlXAuth), username, password, ref content);
150 public void ClearAuthInfo()
152 this.Initialize("", "", "", 0);
155 public HttpStatusCode UploadMedia(IMediaItem item, ref string content)
158 var binary = new List<KeyValuePair<string, IMediaItem>>();
159 binary.Add(new KeyValuePair<string, IMediaItem>("media", item));
161 return httpCon.GetContent(PostMethod,
162 this.CreateTwitterUploadUri("/1.1/media/upload.json"),
170 public HttpStatusCode RetweetStatus(long id, ref string content)
172 Dictionary<string, string> param = new Dictionary<string, string>();
173 param.Add("include_entities", "true");
174 param.Add("include_ext_alt_text", "true");
176 return httpCon.GetContent(PostMethod,
177 this.CreateTwitterUri("/1.1/statuses/retweet/" + id + ".json"),
184 public HttpStatusCode ShowStatuses(long id, ref string content)
186 Dictionary<string, string> param = new Dictionary<string, string>();
187 param.Add("include_entities", "true");
188 param.Add("include_ext_alt_text", "true");
189 return httpCon.GetContent(GetMethod,
190 this.CreateTwitterUri("/1.1/statuses/show/" + id + ".json"),
193 this.CreateRatelimitHeadersDict(),
194 this.CreateApiCalllback("/statuses/show/:id"));
197 public HttpStatusCode HomeTimeline(int? count, long? max_id, long? since_id, ref string content)
199 Dictionary<string, string> param = new Dictionary<string, string>();
201 param.Add("count", count.ToString());
203 param.Add("max_id", max_id.ToString());
204 if (since_id != null)
205 param.Add("since_id", since_id.ToString());
207 param.Add("include_entities", "true");
208 param.Add("include_ext_alt_text", "true");
210 return httpCon.GetContent(GetMethod,
211 this.CreateTwitterUri("/1.1/statuses/home_timeline.json"),
214 this.CreateRatelimitHeadersDict(),
215 this.CreateApiCalllback("/statuses/home_timeline"));
218 public HttpStatusCode UserTimeline(long? user_id, string screen_name, int? count, long? max_id, long? since_id, ref string content)
220 Dictionary<string, string> param = new Dictionary<string, string>();
222 if ((user_id == null && string.IsNullOrEmpty(screen_name)) ||
223 (user_id != null && !string.IsNullOrEmpty(screen_name))) return HttpStatusCode.BadRequest;
226 param.Add("user_id", user_id.ToString());
227 if (!string.IsNullOrEmpty(screen_name))
228 param.Add("screen_name", screen_name);
230 param.Add("count", count.ToString());
232 param.Add("max_id", max_id.ToString());
233 if (since_id != null)
234 param.Add("since_id", since_id.ToString());
236 param.Add("include_rts", "true");
237 param.Add("include_entities", "true");
238 param.Add("include_ext_alt_text", "true");
240 return httpCon.GetContent(GetMethod,
241 this.CreateTwitterUri("/1.1/statuses/user_timeline.json"),
244 this.CreateRatelimitHeadersDict(),
245 this.CreateApiCalllback("/statuses/user_timeline"));
248 public HttpStatusCode Mentions(int? count, long? max_id, long? since_id, ref string content)
250 Dictionary<string, string> param = new Dictionary<string, string>();
252 param.Add("count", count.ToString());
254 param.Add("max_id", max_id.ToString());
255 if (since_id != null)
256 param.Add("since_id", since_id.ToString());
258 param.Add("include_entities", "true");
259 param.Add("include_ext_alt_text", "true");
261 return httpCon.GetContent(GetMethod,
262 this.CreateTwitterUri("/1.1/statuses/mentions_timeline.json"),
265 this.CreateRatelimitHeadersDict(),
266 this.CreateApiCalllback("/statuses/mentions_timeline"));
269 public HttpStatusCode DirectMessages(int? count, long? max_id, long? since_id, ref string content)
271 Dictionary<string, string> param = new Dictionary<string, string>();
273 param.Add("count", count.ToString());
275 param.Add("max_id", max_id.ToString());
276 if (since_id != null)
277 param.Add("since_id", since_id.ToString());
278 param.Add("full_text", "true");
279 param.Add("include_entities", "true");
280 param.Add("include_ext_alt_text", "true");
282 return httpCon.GetContent(GetMethod,
283 this.CreateTwitterUri("/1.1/direct_messages.json"),
286 this.CreateRatelimitHeadersDict(),
287 this.CreateApiCalllback("/direct_messages"));
290 public HttpStatusCode DirectMessagesSent(int? count, long? max_id, long? since_id, ref string content)
292 Dictionary<string, string> param = new Dictionary<string, string>();
294 param.Add("count", count.ToString());
296 param.Add("max_id", max_id.ToString());
297 if (since_id != null)
298 param.Add("since_id", since_id.ToString());
299 param.Add("full_text", "true");
300 param.Add("include_entities", "true");
301 param.Add("include_ext_alt_text", "true");
303 return httpCon.GetContent(GetMethod,
304 this.CreateTwitterUri("/1.1/direct_messages/sent.json"),
307 this.CreateRatelimitHeadersDict(),
308 this.CreateApiCalllback("/direct_messages/sent"));
311 public HttpStatusCode Favorites(int? count, ref string content)
313 Dictionary<string, string> param = new Dictionary<string, string>();
315 param.Add("count", count.ToString());
316 param.Add("include_entities", "true");
317 param.Add("include_ext_alt_text", "true");
319 return httpCon.GetContent(GetMethod,
320 this.CreateTwitterUri("/1.1/favorites/list.json"),
323 this.CreateRatelimitHeadersDict(),
324 this.CreateApiCalllback("/favorites/list"));
327 public HttpStatusCode Search(string words, string lang, int? count, long? maxId, long? sinceId, ref string content)
329 Dictionary<string, string> param = new Dictionary<string, string>();
330 if (!string.IsNullOrEmpty(words)) param.Add("q", words);
331 if (!string.IsNullOrEmpty(lang)) param.Add("lang", lang);
332 if (count != null) param.Add("count", count.ToString());
333 if (maxId != null) param.Add("max_id", maxId.ToString());
334 if (sinceId != null) param.Add("since_id", sinceId.ToString());
336 if (param.Count == 0) return HttpStatusCode.BadRequest;
338 param.Add("result_type", "recent");
339 param.Add("include_entities", "true");
340 param.Add("include_ext_alt_text", "true");
341 return httpCon.GetContent(GetMethod,
342 this.CreateTwitterUri("/1.1/search/tweets.json"),
345 this.CreateRatelimitHeadersDict(),
346 this.CreateApiCalllback("/search/tweets"));
349 public HttpStatusCode SavedSearches(ref string content)
351 return httpCon.GetContent(GetMethod,
352 this.CreateTwitterUri("/1.1/saved_searches/list.json"),
355 this.CreateRatelimitHeadersDict(),
356 this.CreateApiCalllback("/saved_searches/list"));
359 public HttpStatusCode FollowerIds(long cursor, ref string content)
361 Dictionary<string, string> param = new Dictionary<string, string>();
362 param.Add("cursor", cursor.ToString());
364 return httpCon.GetContent(GetMethod,
365 this.CreateTwitterUri("/1.1/followers/ids.json"),
368 this.CreateRatelimitHeadersDict(),
369 this.CreateApiCalllback("/followers/ids"));
372 public HttpStatusCode NoRetweetIds(ref string content)
374 return httpCon.GetContent(GetMethod,
375 this.CreateTwitterUri("/1.1/friendships/no_retweets/ids.json"),
378 this.CreateRatelimitHeadersDict(),
379 this.CreateApiCalllback("/friendships/no_retweets/ids"));
382 public HttpStatusCode RateLimitStatus(ref string content)
384 return httpCon.GetContent(GetMethod,
385 this.CreateTwitterUri("/1.1/application/rate_limit_status.json"),
388 this.CreateRatelimitHeadersDict(),
389 this.CreateApiCalllback("/application/rate_limit_status"));
393 public HttpStatusCode GetLists(string user, ref string content)
395 Dictionary<string, string> param = new Dictionary<string, string>();
396 param.Add("screen_name", user);
398 return httpCon.GetContent(GetMethod,
399 this.CreateTwitterUri("/1.1/lists/list.json"),
402 this.CreateRatelimitHeadersDict(),
403 this.CreateApiCalllback("/lists/list"));
406 public HttpStatusCode UpdateListID(string user, string list_id, string name, Boolean isPrivate, string description, ref string content)
408 string mode = "public";
412 Dictionary<string, string> param = new Dictionary<string, string>();
413 param.Add("screen_name", user);
414 param.Add("list_id", list_id);
415 if (name != null) param.Add("name", name);
416 if (mode != null) param.Add("mode", mode);
417 if (description != null) param.Add("description", description);
419 return httpCon.GetContent(PostMethod,
420 this.CreateTwitterUri("/1.1/lists/update.json"),
427 public HttpStatusCode DeleteListID(string user, string list_id, ref string content)
429 Dictionary<string, string> param = new Dictionary<string, string>();
430 param.Add("screen_name", user);
431 param.Add("list_id", list_id);
433 return httpCon.GetContent(PostMethod,
434 this.CreateTwitterUri("/1.1/lists/destroy.json"),
441 public HttpStatusCode GetListsSubscriptions(string user, ref string content)
443 Dictionary<string, string> param = new Dictionary<string, string>();
444 param.Add("screen_name", user);
446 return httpCon.GetContent(GetMethod,
447 this.CreateTwitterUri("/1.1/lists/subscriptions.json"),
450 this.CreateRatelimitHeadersDict(),
451 this.CreateApiCalllback("/lists/subscriptions"));
454 public HttpStatusCode GetListsStatuses(long userId, long list_id, int? per_page, long? max_id, long? since_id, Boolean isRTinclude, ref string content)
456 //認証なくても取得できるが、protectedユーザー分が抜ける
457 Dictionary<string, string> param = new Dictionary<string, string>();
458 param.Add("user_id", userId.ToString());
459 param.Add("list_id", list_id.ToString());
460 param.Add("include_rts", isRTinclude ? "true" : "false");
461 if (per_page != null)
462 param.Add("count", per_page.ToString());
464 param.Add("max_id", max_id.ToString());
465 if (since_id != null)
466 param.Add("since_id", since_id.ToString());
467 param.Add("include_entities", "true");
468 param.Add("include_ext_alt_text", "true");
470 return httpCon.GetContent(GetMethod,
471 this.CreateTwitterUri("/1.1/lists/statuses.json"),
474 this.CreateRatelimitHeadersDict(),
475 this.CreateApiCalllback("/lists/statuses"));
478 public HttpStatusCode CreateLists(string listname, Boolean isPrivate, string description, ref string content)
480 string mode = "public";
484 Dictionary<string, string> param = new Dictionary<string, string>();
485 param.Add("name", listname);
486 param.Add("mode", mode);
487 if (!string.IsNullOrEmpty(description))
488 param.Add("description", description);
490 return httpCon.GetContent(PostMethod,
491 this.CreateTwitterUri("/1.1/lists/create.json"),
498 public HttpStatusCode GetListMembers(string user, string list_id, long cursor, ref string content)
500 Dictionary<string, string> param = new Dictionary<string, string>();
501 param.Add("screen_name", user);
502 param.Add("list_id", list_id);
503 param.Add("cursor", cursor.ToString());
504 return httpCon.GetContent(GetMethod,
505 this.CreateTwitterUri("/1.1/lists/members.json"),
508 this.CreateRatelimitHeadersDict(),
509 this.CreateApiCalllback("/lists/members"));
512 public HttpStatusCode CreateListMembers(string list_id, string memberName, ref string content)
514 Dictionary<string, string> param = new Dictionary<string, string>();
515 param.Add("list_id", list_id);
516 param.Add("screen_name", memberName);
517 return httpCon.GetContent(PostMethod,
518 this.CreateTwitterUri("/1.1/lists/members/create.json"),
525 public HttpStatusCode DeleteListMembers(string list_id, string memberName, ref string content)
527 Dictionary<string, string> param = new Dictionary<string, string>();
528 param.Add("screen_name", memberName);
529 param.Add("list_id", list_id);
530 return httpCon.GetContent(PostMethod,
531 this.CreateTwitterUri("/1.1/lists/members/destroy.json"),
538 public HttpStatusCode ShowListMember(string list_id, string memberName, ref string content)
540 Dictionary<string, string> param = new Dictionary<string, string>();
541 param.Add("screen_name", memberName);
542 param.Add("list_id", list_id);
543 return httpCon.GetContent(GetMethod,
544 this.CreateTwitterUri("/1.1/lists/members/show.json"),
547 this.CreateRatelimitHeadersDict(),
548 this.CreateApiCalllback("/lists/members/show"));
552 public HttpStatusCode Statusid_retweeted_by_ids(long statusid, int? count, int? page, ref string content)
554 Dictionary<string, string> param = new Dictionary<string, string>();
556 param.Add("count", count.ToString());
558 param.Add("page", page.ToString());
560 param.Add("id", statusid.ToString());
562 return httpCon.GetContent(GetMethod,
563 this.CreateTwitterUri("/1.1/statuses/retweeters/ids.json"),
566 this.CreateRatelimitHeadersDict(),
567 this.CreateApiCalllback("/statuses/retweeters/ids"));
570 public HttpStatusCode GetBlockUserIds(ref string content, long? cursor)
572 var param = new Dictionary<string, string>();
575 param.Add("cursor", cursor.ToString());
577 return httpCon.GetContent(GetMethod,
578 this.CreateTwitterUri("/1.1/blocks/ids.json"),
581 this.CreateRatelimitHeadersDict(),
582 this.CreateApiCalllback("/blocks/ids"));
585 public HttpStatusCode GetMuteUserIds(ref string content, long? cursor)
587 var param = new Dictionary<string, string>();
590 param.Add("cursor", cursor.ToString());
592 return httpCon.GetContent(GetMethod,
593 this.CreateTwitterUri("/1.1/mutes/users/ids.json"),
596 this.CreateRatelimitHeadersDict(),
597 this.CreateApiCalllback("/mutes/users/ids"));
600 public HttpStatusCode GetConfiguration(ref string content)
602 return httpCon.GetContent(GetMethod,
603 this.CreateTwitterUri("/1.1/help/configuration.json"),
606 this.CreateRatelimitHeadersDict(),
607 this.CreateApiCalllback("/help/configuration"));
610 public HttpStatusCode VerifyCredentials(ref string content)
612 return httpCon.GetContent(GetMethod,
613 this.CreateTwitterUri("/1.1/account/verify_credentials.json"),
616 this.CreateRatelimitHeadersDict(),
617 this.CreateApiCalllback("/account/verify_credentials"));
621 private static string _twitterUrl = "api.twitter.com";
622 private static string _twitterUserStreamUrl = "userstream.twitter.com";
623 private static string _twitterStreamUrl = "stream.twitter.com";
624 private static string _twitterUploadUrl = "upload.twitter.com";
626 private Uri CreateTwitterUri(string path)
628 return new Uri(string.Format("{0}{1}{2}", "https://", _twitterUrl, path));
631 private Uri CreateTwitterUserStreamUri(string path)
633 return new Uri(string.Format("{0}{1}{2}", "https://", _twitterUserStreamUrl, path));
636 private Uri CreateTwitterStreamUri(string path)
638 return new Uri(string.Format("{0}{1}{2}", "http://", _twitterStreamUrl, path));
641 private Uri CreateTwitterUploadUri(string path)
643 return new Uri(string.Format("{0}{1}{2}", "https://", _twitterUploadUrl, path));
646 public static string TwitterUrl
648 get { return _twitterUrl; }
652 HttpOAuthApiProxy.ProxyHost = value;
657 private Dictionary<string, string> CreateRatelimitHeadersDict()
659 return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
661 ["X-Access-Level"] = "",
662 ["X-RateLimit-Limit"] = "",
663 ["X-RateLimit-Remaining"] = "",
664 ["X-RateLimit-Reset"] = "",
665 ["X-Rate-Limit-Limit"] = "",
666 ["X-Rate-Limit-Remaining"] = "",
667 ["X-Rate-Limit-Reset"] = "",
668 ["X-MediaRateLimit-Limit"] = "",
669 ["X-MediaRateLimit-Remaining"] = "",
670 ["X-MediaRateLimit-Reset"] = "",
674 private CallbackDelegate CreateApiCalllback(string endpointName)
676 return (sender, code, headerInfo, content) =>
678 if (code < HttpStatusCode.InternalServerError)
679 MyCommon.TwitterApiInfo.UpdateFromHeader(headerInfo, endpointName);
683 public HttpStatusCode UserStream(ref Stream content,
688 Dictionary<string, string> param = new Dictionary<string, string>();
691 param.Add("replies", "all");
693 if (!string.IsNullOrEmpty(trackwords))
694 param.Add("track", trackwords);
696 return httpCon.GetContent(GetMethod,
697 this.CreateTwitterUserStreamUri("/1.1/user.json"),
703 public HttpStatusCode FilterStream(ref Stream content,
707 //文中の日本語キーワードに反応せず、使えない(スペースで分かち書きしてないと反応しない)
708 Dictionary<string, string> param = new Dictionary<string, string>();
710 if (!string.IsNullOrEmpty(trackwords))
711 param.Add("track", string.Join(",", trackwords.Split(" ".ToCharArray())));
713 return httpCon.GetContent(PostMethod,
714 this.CreateTwitterStreamUri("/1.1/statuses/filter.json"),
720 public void RequestAbort()
722 httpCon.RequestAbort();
725 public object Clone()
727 HttpTwitter myCopy = new HttpTwitter();
728 myCopy.Initialize(this.AccessToken, this.AccessTokenSecret, this.AuthenticatedUsername, this.AuthenticatedUserId);