みむらです。
ひとまず、おべんきょーということで、後からも分かるように、
変数を多く使って文字列出力をふんだんに出しながら。
ソースコードが、海から来た侵略者に侵略されていますが、
そんなもの全く気にしない、むしろ、侵略されていないでゲソ!
—-
参考資料:
* http://oauth.net/core/1.0
* http://hueniverse.com/oauth/guide/authentication/
* https://dev.twitter.com/docs/auth/authorizing-request/
—-
https://gist.github.com/1395485
using System; using System.Diagnostics; using System.IO; using System.Net; using System.Security.Cryptography; using System.Text; using System.Web; /* * この辺を参考に: * * http://oauth.net/core/1.0 * http://hueniverse.com/oauth/guide/authentication/ * https://dev.twitter.com/docs/auth/authorizing-request */ namespace Direct_Commit_Twitter { class Program { static void Main(string[] args) { // // 使うパラメータは次のようなもの。 // // OAuth Consumer Key : Consumer Key そのまま。 // OAuth Token : Access Token そのまま。 (今回はこれも取得。) // OAuth Nonce : ランダム文字列を与える。 (毎回変更する。) // OAuth Signature : OAuth Signature 以外の値で HMAC-SHA1 をとった値。 // OAuth Signature Method : Twitter は HMAC-SHA1 指定っぽいので HMAC-SHA1. // OAuth Time Stamp : UNIX 時間 (1970-01-01 UTC からの秒数) を与える。 // : (今回は GetUNIXTime() メソッドで取得します。) // OAuth Version : 今回は 1.0 を使うので、1.0. // string consumer_key = "oDcUp76alv6VctYvRx2g"; string consumer_secret = "mg1U9TEFVafIPQm0Y0YuLR8EZatXiDBvPLiiCConzbg"; string access_token = ""; string access_secret = ""; string tweet_text = "ゲソーゲソー"; /************************ 以下、黙々と処理 ********************/ string[] verify_token; if (access_token == "" || access_secret == "") { #region 01. Request Token を取得しなイカ? { Console.WriteLine("01 - Token を取得しなイカ?"); Console.WriteLine("-------------------------------------------------"); Random rand = new Random(); byte[] nonce_b = new byte[64]; rand.NextBytes(nonce_b); string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString(); long unixtime = GetUNIXTime(); // // OAuth Signature 生成のために、それ以外で仮のリクエスト文字列を作成する。 // この際、各パラメータは ABC 順にソートされている必要がある。 // string signature_request = "POST&" + UrlEncode("https://api.twitter.com/oauth/request_token"); signature_request += "&" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, null, null, null)); // // ちゃんとしたリクエスト文字列を作る。 // string signature = GetSignature(consumer_secret, null, signature_request); string param = MakeParamString(consumer_key, nonce, signature, unixtime, null, null, null); DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, null, null, null); return; // // 問い合わせ。 // Console.WriteLine("* Access : https://api.twitter.com/oauth/request_token?" + param); HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/oauth/request_token?" + param); hwr.Method = "POST"; WebResponse ret = hwr.GetResponse(); verify_token = new StreamReader(ret.GetResponseStream()).ReadToEnd().Split('&'); ret.Close(); Console.WriteLine(); Console.WriteLine("Response : "); foreach (string s in verify_token) Console.WriteLine("> " + s); } #endregion #region 02. Access Token を取得しなイカ? { Console.WriteLine(); Console.WriteLine("02 - Access Token を取得しなイカ?"); Console.WriteLine("-------------------------------------------------"); string request_token = ""; string request_secret = ""; // // ブラウザ開いて認証。 // foreach (string s in verify_token) { int p = s.IndexOf("oauth_token="); if (p != -1) { request_token = s.Substring(p + "oauth_token=".Length); break; } } Console.WriteLine("- OAuth Token : " + request_token); Console.WriteLine("* Browser Open : https://twitter.com/oauth/authorize?oauth_token=" + request_token); Process.Start("https://twitter.com/oauth/authorize?oauth_token=" + request_token); // // PIN を入力させる。 // Console.Write("\nINPUT PIN : "); string pin = Console.ReadLine(); foreach (string s in verify_token) { int p = s.IndexOf("oauth_token_secret="); if (p != -1) { request_secret = s.Substring(p + "oauth_token_secret=".Length); break; } } // // 以下 Twitter ともくもく通信。 // Random rand = new Random(); byte[] nonce_b = new byte[64]; rand.NextBytes(nonce_b); string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString(); long unixtime = GetUNIXTime(); // // Signature 生成のための一時的なリクエスト文字列を作成。 // string signature_request = "POST&" + UrlEncode("https://api.twitter.com/oauth/access_token"); signature_request += "&" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, request_token, pin, null)); string signature = GetSignature(consumer_secret, request_secret, signature_request); string param = MakeParamString(consumer_key, nonce, signature, unixtime, request_token, pin, null); DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, request_token, request_secret, pin); // // 問い合わせ。 // Console.WriteLine("* Access : https://api.twitter.com/oauth/access_token?" + param); HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/oauth/access_token?" + param); hwr.Method = "POST"; hwr.Headers.Add("Authorization", "OAuth"); WebResponse ret = hwr.GetResponse(); verify_token = new StreamReader(ret.GetResponseStream()).ReadToEnd().Split('&'); ret.Close(); Console.WriteLine(); Console.WriteLine("Response : "); foreach (string s in verify_token) { if (s.IndexOf("oauth_token=") != -1) access_token = s.Substring(s.IndexOf("=") + 1); if (s.IndexOf("oauth_token_secret=") != -1) access_secret = s.Substring(s.IndexOf("=") + 1); Console.WriteLine("> " + s); } } #endregion } #region 03. つぶやかなイカ? { Console.WriteLine(); Console.WriteLine("03 - つぶやかなイカ?"); Console.WriteLine("-------------------------------------------------"); Random rand = new Random(); byte[] nonce_b = new byte[64]; rand.NextBytes(nonce_b); string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString(); long unixtime = GetUNIXTime(); string tweet_data = UrlEncode(tweet_text); string signature_request = "POST&" + UrlEncode("https://api.twitter.com/1/statuses/update.xml"); signature_request += "&include_entities%3Dtrue%26" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, access_token, null, tweet_data)); string signature = GetSignature(consumer_secret, access_secret, signature_request); string header_param = "OAuth oauth_consumer_key=\"" + UrlEncode(consumer_key) + "\",oauth_signature_method=\"HMAC-SHA1\"," + "oauth_timestamp=\"" + unixtime + "\",oauth_nonce=\"" + UrlEncode(nonce) + "\"," + "oauth_version=\"1.0\",oauth_token=\"" + UrlEncode(access_token) + "\"," + "oauth_signature=\"" + UrlEncode(signature) + "\","; DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, access_token, access_secret, null); Console.WriteLine("* Access : https://api.twitter.com/1/statuses/update.xml"); Console.WriteLine("* Tweet at : " + tweet_text); HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/1/statuses/update.xml"); hwr.Method = "POST"; hwr.ServicePoint.Expect100Continue = false; hwr.Headers.Add(HttpRequestHeader.Authorization, header_param); hwr.ContentType = "application/x-www-form-urlencoded"; var s = new StreamWriter(hwr.GetRequestStream()); s.Write("status=" + tweet_data + "&include_entities=true"); s.Close(); WebResponse ret = hwr.GetResponse(); Console.WriteLine(); Console.WriteLine("Response:"); Console.WriteLine("> "+(new StreamReader(ret.GetResponseStream()).ReadToEnd())); } #endregion } // UNIX 時間を返す。 static long GetUNIXTime() { return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; } // URLエンコード (どうやらエスケープ文字は大文字にしないといけないらしい。) static string UrlEncode(string str) { string s = HttpUtility.UrlEncode(str); return _UrlEncodeUpper(s); } static string _UrlEncodeUpper(string str) { int p = str.IndexOf("%"); if (p != -1) { str = str.Substring(0, p) + str.Substring(p, 3).ToUpper() + _UrlEncodeUpper(str.Substring(p + 3)); } return str; } // パラメータ文字列を生成 static string MakeParamString(string oauth_consumer_key, string oauth_nonce, string oauth_signature, long oauth_timestamp, string oauth_token, string oauth_verifier, string status) { string param = "oauth_consumer_key=" + oauth_consumer_key + "&oauth_nonce=" + oauth_nonce; if (oauth_signature != null) param += "&oauth_signature=" + oauth_signature; param += "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=" + oauth_timestamp; if (oauth_token != null) param += "&oauth_token=" + oauth_token; if (oauth_verifier != null) param += "&oauth_verifier=" + oauth_verifier; param += "&oauth_version=1.0"; if (status != null) param += "&status=" + status; return param; } // Consumer Secret をKey とした、リクエスト文字列のハッシュを求める。 static string GetSignature(string consumer_secret, string access_token_secret, string param) { HMACSHA1 hmacsha1 = new HMACSHA1(); hmacsha1.Key = Encoding.ASCII.GetBytes(consumer_secret + "&" + access_token_secret); byte[] hash = hmacsha1.ComputeHash(Encoding.ASCII.GetBytes(param)); return Convert.ToBase64String(hash); } // よくやる出力をまとめてみる。 static void DebugParamOut(string oauth_consumer_key, string oauth_consumer_secret, string oauth_nonce, string oauth_signature, long oauth_timestamp, string oauth_token, string oauth_token_secret, string oauth_verifier) { Console.WriteLine("- OAuth Consumer Key = " + oauth_consumer_key); Console.WriteLine("- OAuth Consumer Secret = " + oauth_consumer_secret); Console.WriteLine("- OAuth Nonce = " + oauth_nonce); if (oauth_signature != null) Console.WriteLine("- OAuth Signature = " + oauth_signature); Console.WriteLine("- OAuth Time Stamp = " + oauth_timestamp); if (oauth_token != null) Console.WriteLine("- OAuth Access Token = " + oauth_token); if (oauth_token_secret != null) Console.WriteLine("- OAuth Access Token Secret = " + oauth_token_secret); if (oauth_verifier != null) Console.WriteLine("- OAuth Verifier = " + oauth_verifier); } } }
とりあえず、記事自体がむちゃくちゃ長くなるので、
解説云々は次の記事に。