Archive for the ‘Ruby’ Category

Ruby Twitter Gem(とRuby OAuth Gem)のバージョンが変わったら動かなくなった件

前回までの話
Ruby Twitter GemでOAuth認証のクライアントを作る

サーバの移行でバージョンが変わりました。
すると、こーんなエラーが出て動かなくなりました。

/usr/local/lib/ruby/gems/1.8/gems/oauth-0.4.3/lib/oauth/client/helper.rb:64:in `amend_user_agent_header’: uninitialized constant OAuth::VERSION (NameError)

いろいろ調べた結果、こうするのが正解だったようです。

「クライアントプログラム側でOAuth::VERSIONを定義する」
定義してないプログラム用に、〜/oauth/version.rb を作成しました

OAuth::VERSION = "0.4.3"

これをやったあと、クライアントプログラムでOAuthまわりの部分に1行追加

gem 'oauth'
require 'oauth/consumer'
require 'oauth/version'         # ← これを追加!

Ruby twitter gemを使ってる場合は、この追加は不要です。このまま。

gem 'twitter'
require 'twitter'

以下は、「まいんぼたん」的変更。
twitter gem の0.9.12でupdate時にJSON処理まわりで例外を吐いてしまうようなので、rescueで強引に対策。

tw_oauth = Twitter::OAuth.new( OAUTH_CONSUMER_KEY , OAUTH_CONSUMER_SECRET )
tw_oauth.authorize_from_access( oa_token  , oa_secret )

client = Twitter::Base.new(tw_oauth)
begin
   res = client.update( in_post )
rescue
   reserr = 1
end

参考:Togetter – 「RubyでOAuthをごにょごにょ」

Ruby Twitter GemでOAuth認証のクライアントを作る

Ruby Twitter Gemというのがあります。これを使えば楽にできます。
前、botを作るところでとりあげました。
Ruby Twitter Gemでボットを作ろう « てっく★ゆきろぐ Rev2
基本的には、上記でやってることと変わりません。
認証のところが違うくらいです。

#!/usr/bin/ruby

require 'rubygems'
gem 'twitter'
require 'twitter'

# この2行が違うだけ
tw_oauth = Twitter::OAuth.new( OAUTH_CONSUMER_KEY , OAUTH_CONSUMER_SECRET )
tw_oauth.authorize_from_access( oauth_access_token  , oauth_access_secret )

client = Twitter::Base.new(tw_oauth)
client.update( postdata )

以前HTTP Basic認証のときは、Twitter::HTTPAuth を使ってましたが、OAuth認証の場合は、Twitter::OAuth を使います。
違いはこれだけ。

これだけでは半分。
OAuthを使う場合、認証が必要になります。
この認証を経て、APIにアクセスするためのアクセストークンが取得できます。
それでは、認証開始から、アクセストークンをもらってくるまでの処理を書いてみたいと思います。
流れについては、twitterでOAuthを使う方法(その1:認証まで): てっく☆ゆきろぐ にて書いてありますので、そちらの解説を参照いただければなと思います。
※あらかじめ、アプリケーション管理画面でコンシューマキー等は取得しておいてくださいね。

●ステップ1:リクエストが来たので、twitterへリクエストトークンを要求する。その後認証画面へリダイレクト
今回の処理には、普通にCGIを使うことにします。
CGI処理は、Rubyにもともと入ってるcgiライブラリを利用することにします。
そして、セッション管理には同じくRubyにもともと入ってるcgi/sessionライブラリを利用します。
そして、OAuthの処理をしてくれるのが、Ruby OAuth GEM
入れるためにはこれ一発。

# gem install oauth

そんなわけで使用宣言、こうなります。

#!/usr/bin/ruby

require 'rubygems'
gem 'oauth'
require 'cgi'
require 'cgi/session'
require 'oauth/consumer'

CGIのセッション開始処理。
今回はセッション変数にrequest_token等、各ユーザーごとの機密情報が入ってきますので、tmpdirの場所を「自分の手の届く」適切な場所に変更します。

cgi = CGI.new
session = CGI::Session.new(cgi,{"new_session"=>true,"tmpdir"=>workdir })

そして、ここからが、OAuthの処理本体となります。
まず、OAuth::Consumerのインスタンスを作ります。
オプションでコールバック先のURLを与えるのを忘れないでくださいね!

onsumer = OAuth::Consumer.new( OAUTH_CONSUMER_KEY , OAUTH_CONSUMER_SECRET , {
    :site=>"http://twitter.com"
    })
optprm = { :oauth_callback=>"(コールバック先のURL)" }
request_token = consumer.get_request_token( optprm , { } )

これで、リクエストトークンが要求されて、request_token に入ってきます。
取得されたリクエストトークン情報をセッション変数に入れておきます。(あとで使うため)
入れたあと、authorizeのURLに移動させます。

session["request_token"] = request_token.token
session["request_token_secret"] = request_token.secret
print cgi.header( 'Location' => request_token.authorize_url )

これで、このCGIにアクセスすることによって、リクエストトークン取得から、認証画面への移動までがなされます。

●ステップ2:サービスプロバイダでの認証
リダイレクトされて、サービスプロバイダ(この場合twitter)の認証画面に飛びます。
2010021101
「Allow」ボタンが押されたら、さきほど与えたコールバック先URLに飛ばされます。

●ステップ3:アクセストークンの取得
コールバックされた先で、サービスプロバイダへ再度アクセスして、アクセストークンをもらいます。
必要なライブラリはステップ1と同じなので割愛。
今度はサービスプロバイダからパラメータがくるので、CGIでのパラメータ取得必須。
それと、CGI::Sessionの引数を間違えて、セッション初期化しないようにね。

cgi = CGI.new
session = CGI::Session.new(cgi,{"tmpdir"=>workdir })
oauth_token = cgi["oauth_token"]
oauth_vrfy  = cgi["oauth_verifier"]

そして、アクセストークン要求を行います。
このとき、ステップ1で使ったリクエストトークンの情報が必要になります。

consumer = OAuth::Consumer.new( OAUTH_CONSUMER_KEY , OAUTH_CONSUMER_SECRET , {
    :site=>"http://twitter.com"
    })

# ステップ1で作ったリクエストトークンを利用する
request_token = OAuth::RequestToken.new(
  consumer,
  session["request_token"] ,
  session["request_token_secret"]
)

# アクセストークン要求
prm = { :oauth_verifier => oauth_vrfy }
access_token = request_token.get_access_token( prm )

これでアクセストークンの取得ができます。
取得したアクセストークンはsessionに入れておきます。

session["access_token"] = access_token.token
session["access_secret"] = access_token.secret

print cgi.header( "Location"=>"main.cgi" )

余談ですが、ここで各種動作が正規ルートで来ているかのチェック用に(要するにCSRF対策で)確認用のキーを作るのもいいでしょう(ここでは敢えて割愛)。
※CSRFってなんじゃってかたのために。以下の記事あたり参考になると思いますよ!
 [はまちちゃんのセキュリティ講座]ここがキミの脆弱なところ…!:第2回 しーさーふって何ですか?|gihyo.jp … 技術評論社

以上で、アクセストークン等の、必要な情報の取得は終わりです。
あとは使うところで、

oauth_access_token = session["access_token"] 
oauth_access_secret = session["access_secret"]
tw_oauth = Twitter::OAuth.new( OAUTH_CONSUMER_KEY , OAUTH_CONSUMER_SECRET )
tw_oauth.authorize_from_access( oauth_access_token  , oauth_access_secret )
#以下略

と、するだけ。

・・・はい。
実はこの実装のサンプルが、まいんぼたんだったりします(笑)

さくらのレンタルサーバにRubyGemsいれた

必要が出てきたのでw

$ wget http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz
$ cd rubygems-1.3.5
$ ruby setup.rb --prefix=/home/(自分のユーザ名)/local

展開はここまで。あとは、~/.cshrc への設定。以下を追加。

setenv PATH $HOME/local/bin:$PATH
setenv RUBYLIB $HOME/local/lib
setenv GEM_HOME $HOME/local/lib/ruby/gem

ちゃんと入ってるかはこれで確認。

$ gem18 --version

参考:さくらのレンタルサーバーに RubyGems をインストールする手順 – ishimarumの日記

Ruby Twitter Gemでボットを作ろう

Ruby Twitter Gemを使えば簡単に扱えます。

インストールのしかたは、

# gem install twitter

だけでOK。

とりあえず何かをpostするだけならこう。
あ、ファイルのエンコーディングは UTF-8 で御願いしますね。

#!/usr/bin/ruby

require 'rubygems'
gem 'twitter'
require 'twitter'

msg = "ひるぽっぽ★"
httpauth = Twitter::HTTPAuth.new( Twitter_ID , Twitter_PW  )
o_twit = Twitter::Base.new( httpauth )
o_twit.update( msg )

リプライの取得はこう。

#!/usr/bin/ruby

require 'rubygems'
gem 'twitter'
require 'twitter'

filehandle = open( "laststatus.txt" , "r")
laststatus = filehandle.gets.to_i
filehandle.close
lastnum = laststatus.to_i

httpauth = Twitter::HTTPAuth.new( Twitter_ID , Twitter_PW  )
o_twit = Twitter::Base.new( httpauth )
mentions = o_twit.mentions
mentions.each do |m|
  statid = m.id.to_i
  repl = m.user.screen_name
  if ( maxstatid < statid )
    maxstatid = statid
  end
  next if ( laststatus >= statid )   # 既に応答した人はスキップ
  n = m.text
  # n に対して処理して、nout でリプライを返す。
  nout = "@" + repl + " "
  nout <<  "(=゚ω゚)ノぃょぅ"
  o_twit.update( nout )
end

filehandle = File.open( "laststatus.txt" , "w")
filehandle.puts maxstatid
filehandle.close

mentions 等に返ってくるのは、APIから取得したデータが配列で入っています。
APIから返ってくるXMLフォーマットがわかっていれば、難しくないかなとは思います。
mentions[n].text で本文、
mentions[n].id がtweetのid、
mentions[n].user.screen_name が、発言者のスクリーンネーム。