RubyでTwitterにツイートをキメてみる
前回までのあらすじ
- RubyでTwitterのOAuth認証をしてみる - kk_Atakaの日記
- RubyでTwitterのOAuth認証をしてみる その2 - kk_Atakaの日記
- RubyでTwitterのタイムラインを取得してみる - kk_Atakaの日記
ターミナルからOAuth認証をキメて、タイムラインを見られるようになりました。最後にターミナルからツイートが出来れば一応Twitterの見る・書くがライブラリ無しでできたことになります。
ツイートする方法
- signatureを作成する。必要な値は以下のとおり。
- oauth_consumer_key
- oauth_nonce
- oauth_signature
- oauth_signature_method
- oauth_timestamp
- oauth_token
- oauth_version
- status New!
statusっていうのがツイートの本文ですね。signature作成するのにエスケープします。作成後のheaderはこんな感じ。*1statusには「確認確認」って入ってます。
{ "oauth_nonce"=>"3c8293f9c5a0295148d428a26edb9f46", "oauth_timestamp"=>"1295784908", "oauth_signature_method"=>"HMAC-SHA1", "oauth_consumer_key"=>"XXXXXXXXXXXXXXXXXXXXXX", "oauth_token"=>"99999999-YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY", "oauth_signature"=>"UKt1BmJ+UWNWrSmBuAyJ40iiCNY=", "status"=>"%E7%A2%BA%E8%AA%8D%E7%A2%BA%E8%AA%8D", "oauth_version"=>"1.0" }
signature作成後
- signatureを作成したら、headerからstatusを消します
- 残ったheaderをアルファベット順に並べ、xxx=yyy,vvv=zzz……の形で連結します。連結後はこんな感じ
oauth_consumer_key=XXXXXXXXXXXXXXXXXXXXXX,oauth_nonce=341d852d61cdc3c22e3e847b0ab69d20,oauth_signature=MR5WEJ1qHuE49ozgRYduNJ%2BBiCs%3D,oauth_signature_method=HMAC-SHA1,oauth_timestamp=1295785315,oauth_token=99999999-YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY,oauth_version=1.0
- 連結した上記の値をAuthorizationヘッダに入れる。入れた後はこんな感じ。
"Authorization"=>"OAuth oauth_consumer_key=XXXXXXXXXXXXXXXXXXXXXX,oauth_nonce=341d852d61cdc3c22e3e847b0ab69d20,oauth_signature=MR5WEJ1qHuE49ozgRYduNJ%2BBiCs%3D,oauth_signature_method=HMAC-SHA1,oauth_timestamp=1295785315,oauth_token=99999999-YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY,oauth_version=1.0"
- Authorizationヘッダを作成したらhttp://api.twitter.com/1/statuses/home_timeline.jsonへPOST。また、ツイート本文を「status=本文」の形でくっつける
結果
以上で、Twitterにツイートが完了しました! おっぱいきたーー
ソース
ソースはこんな感じです。
# -*- encoding: UTF-8 -*- require 'openssl' require 'uri' require 'net/http' require 'nkf' require 'time' # 署名 def sigunature(method, consumer_secret, oauth_token_secret, url, oauth_header=nil) # sigunature_keyの作成 # リクエストトークン時は"CONSUMER_SECRET&"(アンドが入っている) # アクセストークン時は"CONSUMER_SECRET&OAUTH_TOKEN_SECRET"として使用 sigunature_key = consumer_secret + "&" if !oauth_token_secret.nil? then sigunature_key += oauth_token_secret end param = sort_and_concat(oauth_header) # メソッド + URL + パラメータ value = method + "&" + escape(url) + "&" + escape(param) # hmac_sha1 sha1 = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, sigunature_key, value) # base64 base64 = [sha1].pack('m').gsub(/\n/, '') return base64 end # 文字列のエスケープ(: / = %をエスケープする。. _ -はそのまま) def escape(value) URI.escape(value, Regexp.new("[^a-zA-Z0-9._-]")) end # oauth_headerの情報をアルファベット順に並べ替え & で結合 def sort_and_concat(oauth_header) oauth_header_array = oauth_header.sort param = "" oauth_header_array.each do |params| for i in 1..params.length param += params[i-1] if i % params.length == 0 param += "&" else param += "=" end end end param = param.slice(0, param.length-1) end # ------------------------------------------------------------- update_url = "http://twitter.com/statuses/update.json" url = update_url # コマンドプロンプトはutf8変換 text = escape(ARGV[0]) # text = escape(NKF.nkf('-w', ARGV[0])) proxy = ARGV[1] # Twitterで登録したらもらえる consumer_key = "XXXXXXXXXXXXXXXXXXX" consumer_secret = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY" # Twitterからもらえるリクエストトークン(最初は使わない) oauth_token = "11111111-ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" oauth_token_secret = "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" # oauthパラメータたち(決め打ちのもの) oauth_header = { # Consumer Key "oauth_consumer_key" => consumer_key, # 一意な値 "oauth_nonce" => OpenSSL::Digest::Digest.hexdigest('MD5', "#{Time.now.to_f}#{rand}"), # 署名方式(HMAC-SHA1) "oauth_signature_method" => "HMAC-SHA1", # リクエスト生成時のタイムスタンプのミリ秒 "oauth_timestamp" => Time.now.to_i.to_s, # バージョン(1.0) "oauth_version" => "1.0", # アクセストークン "oauth_token" => oauth_token } # headerにツイート追加 oauth_header["status"] = text # 署名生成 oauth_header["oauth_signature"] = sigunature("POST", consumer_secret, oauth_token_secret, url, oauth_header) # headerからツイート削除 oauth_header.delete("status") # 署名エンコード oauth_header["oauth_signature"] = escape(oauth_header["oauth_signature"]) param = sort_and_concat(oauth_header) param = param.gsub('&', ',') header = { "Authorization" => "OAuth " + param } # POST uri = URI.parse(update_url) proxy_class = Net::HTTP::Proxy(proxy, 8080) http = proxy_class.new(uri.host) http.start do |http| res = http.post(uri.path, "status=#{text}", header) if res.code == "200" then print "#{res.code} tweet: #{ARGV[0]}\n" else print "ERROR: #{res.code}\n #{res.body}\n" end end
*1:実際はインデントとかなし。