Twitterのbotを作ってみたかったので、前準備としてOAuth認証を試してみる。
ほとんど人のスクリプトを流用しただけなので詳しくは[しばそんノート]TwitterのbotをOAuthに対応させるをご覧ください。
botにするには「適当なタイミングで起動」「取得したタイムラインを解析」「結果に基づいてお返事」するように改造すればいい。”適当なタイミング”は、普通はOSのタイマー(cronとか)を使うけど、Twitterからの「返事が来たよコールバック」を使う事もできるらしい。([修正]:Twitterのcallback URLは「返事が来たよ」ではなく「認証通ったよ」コールバックらしい、認証が出来たときに設置したbotのURLにリダイレクトしてくれるんだってさ。)
それはさておき以下本編です。
ほとんど人のスクリプトを流用しただけなので詳しくは[しばそんノート]TwitterのbotをOAuthに対応させるをご覧ください。
botにするには「適当なタイミングで起動」「取得したタイムラインを解析」「結果に基づいてお返事」するように改造すればいい。”適当なタイミング”は、普通はOSのタイマー(cronとか)を使うけど、
それはさておき以下本編です。
OAuthってなに?
OAuth(おーおーす、ぜろおーすではない)は認証プロトコルの一種で「あらかじめ信頼関係を構築したサービス間で、ユーザーの同意のもとに操作権限を受け渡しするための仕組み」らしい。ようはサービスの提供者が持っている権限(ツィートの投稿とか)の一部をあらかじめ手続きをした人に貸してあげるというもの、本来ならTwitterのサイトにログインしないと出来ない事を外部からでも出来るようにしたくて作ったらしい。
認証の手続きをおおざっぱにいうと
- コンシューマ登録
- リクエスト・トークン要求とユーザの同意確認
- アクセス・トークン要求
- (もらった権限に基づいて)APIに接続
TwitterでOAuth認証
というわけで、RubyでOAuth認証を用いてTwitterに接続してタイムラインの取得と ツィートを行うスクリプトを試してみた。[しばそんノート]TwitterのbotをOAuthに対応させるのスクリプトを利用。事前準備
今回はRubyを使うので「Ruby」「RubyGem」を用意しておく。そして「oauth」と「json」のライブラリをgemで用意しておく。% ruby --version ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0] % gem --version 1.3.5 %sudo gem install oauth %sudo gem install json文字コードをUTF8で統一しておくことも忘れずに!
ruby-oauthはRuby1.9系に完全には対応していないのでパッチを用意するということなので、Ruby1.9以上の人は[しばそんノート]TwitterのbotをOAuthに対応させるからoauth-patch.rbを貰っとくこと。
コンシューマ登録
まずはTwitterにログインしておく、スクリプトはこの時にログインしていたユーザに対して操作(タイムライン取ってきたりコメント投稿したり)する。「http://twitter.com/oauth_clients」にアクセスして登録手続き、「アプリケーション名」と「アプリケーションの説明」「アプリケーションのウェブサイトURL」は必須らしい。今回はwebサービスとして動かす訳ではないので「アプリケーションの種類」は”クライアントアプリケーション”、タイムラインの読み込みとツィートの投稿を行うので「Default Access type」は”Read & Write”にする。
うまくいくと下図のように「Consumer key」「Consumer secret」などが貰えるのでメモっておく。
リクエスト・トークン要求とユーザの同意確認、アクセス・トークン要求
次はスクリプトを使って「リクエスト・トークン要求とユーザの同意確認」と「アクセス・トークン要求」を行う。 「CONSUMER_KEY」と「CONSUMER_SECRET」はさっきのあれを使う[しばそんノート]TwitterのbotをOAuthに対応させるを少々改変
twitter-oauth.rb
#!/usr/bin/env ruby # coding: utf-8 #アクセストークンを取得する #http://d.hatena.ne.jp/shibason/20090802/1249204953 require 'rubygems' require 'oauth' #require 'oauth-patch' #Rubyが1.9以上の人 #以下2つを書き換え CONSUMER_KEY = "Consumer keyを書く" CONSUMER_SECRET = "Consumer secretを書く" #コンシューマとしてアクセス consumer = OAuth::Consumer.new( CONSUMER_KEY, CONSUMER_SECRET, {:site => 'http://api.twitter.com', :request_token_path => '/oauth/request_token', :authorize_path => '/oauth/authorize', :access_token_path => '/oauth/access_token'} ) #コンシューマ・トークンを取得 #「:oauth_callback=>"oob"」=「コールバックは使わない」 request_token = consumer.get_request_token(:oauth_callback => "oob") #URLにアクセス puts "Access this URL and approve => #{request_token.authorize_url}" #認証コードを入力 print "Input OAuth Verifier: " oauth_verifier = gets.chomp.strip #アクセス・トークンを取得 access_token = request_token.get_access_token( :oauth_verifier => oauth_verifier ) puts "Access token: #{access_token.token}" puts "Access token secret: #{access_token.secret}"
実行すると以下のように表示されるので、URLにアクセス。
% ruby twitter-oauth.rb Access this URL and approve => なんか長いURL Input OAuth Verifier:(*エラーが出る人は下をチェケ) アクセスするとTwitterのサイトが表示されて「認証しますか?」と聞かれるので認証、そうすると八桁くらいの認証コードが貰えるので「Input OAuth Verifier」に入力。
Input OAuth Verifier: サイトで貰った認証コード Access token: なんか長い英数字1 Access token secret: なんか長い英数字2そうすると「Access token」と「Access token secret」が貰えるのでメモっておく。
APIへのアクセス
ここまでで「Consumer key」「Consumer secret」「Access token」「Access token secret」の4つがそろうので、こんどはこいつらを使ってTwitter APIにアクセス!以下のスクリプトは例によって[しばそんノート]TwitterのbotをOAuthに対応させるのものです感謝しつつ使いましょう。
#!/usr/bin/env ruby # coding: utf-8 require 'rubygems' require 'oauth' #require 'oauth-patch' #Ruby1.9以上の人 require 'json' #キーなどを書いておく CONSUMER_KEY = 'Consumer keyを書く' CONSUMER_SECRET = 'UConsumer secretを書く' ACCESS_TOKEN = 'Access tokenを書く' ACCESS_TOKEN_SECRET = 'Access token secretを書く' # コンシューマとして接続 consumer = OAuth::Consumer.new( CONSUMER_KEY, CONSUMER_SECRET, :site => 'http://twitter.com' ) #アクセス・トークンの生成 access_token = OAuth::AccessToken.new( consumer, ACCESS_TOKEN, ACCESS_TOKEN_SECRET ) ##以下、TwitterAPIへアクセス例 # タイムラインを取得 response = access_token.get('http://twitter.com/statuses/friends_timeline.json') #時系列に(古い順に)出力 JSON.parse(response.body).reverse_each do |status| user = status['user'] puts "#{user['name']}(#{user['screen_name']}): #{status['text']}" end # Tweetの投稿 response = access_token.post( 'http://twitter.com/statuses/update.json', 'status'=> 'このメッセージはOAuth認証を通して投稿しています。' )うまくいくと下記のようにタイムラインが取得でき、Twitterアカウントに 「このメッセージはOAuth認証を通して投稿しています。」と投稿されている。
% ruby twitter-oauth-access.rb パチュリー・ノーレッジbot(Patchouli0): 土水符「ノエキアンデリュージュ」! 十六夜咲夜BOT(SakuyasanBOT): 美鈴!またサボっていますね! 古明地こいし(Komeiji_Koishi): 地霊殿の方が騒がしいわね (以下略)(*エラーが出る人は下をチェケ)
その他のAPIについてはTwitter APIを参照してくださいな。
ダメだったメモ
なんかまったく同じソースコードなのにあるPCでは動き、別のPCでは動かなかった、たぶんどっかの環境設定がおかしいんだろうけどとりあえずメモっとく。うまくいかなかった環境は学科の学生用サーバ、OAuth認証をしようとするところでエラー、、、ネットワークの設定とかがアレなのかもしれない。
Fedoracore 10
ruby 1.8.6 (2009-03-31 patchlevel 368) [i386-linux]
gem 1.3.1
json_pure (1.4.3)
oauth (0.4.0)
エラー内容は「401 Unauthorized」、認証が通らないらしい。
%ruby twitter-oauth.rb /usr/lib/ruby/gems/1.8/gems/oauth-0.4.0/lib/oauth/consumer.rb:215:in `token_request': 401 Unauthorized (OAuth::Unauthorized) from /usr/lib/ruby/gems/1.8/gems/oauth-0.4.0/lib/oauth/consumer.rb:136:in `get_request_token' from twitter-oauth.rb:21
うまくいった環境は自宅のMacBook、一般的なプロバイダーにデフォルト設定のファイアウォール
MacOSX 10.6.3
ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0]
gem 1.3.5
json (1.4.3)
oauth (0.4.0)
また、このエラーはTwitter側からはねられてるときも発生するらしい。 [Newbie.new(’sillow’).upto(:a_developer) { write some_code }]Twitter の OAuth 認証の Request token の生成で 401 Unauthorized が出るときの原因のひとつ
ダメだったメモ2
タイムラインの表示のとこで使ってる「reverse_each」は新しい関数なので、古いRubyを使ってるときは「each」で我慢する。ダメだったメモ3
たまにツィートが失敗してることがある、原因は究明中。 [追記]「前に投稿したのと全く同じ文章は、しばらくの間は投稿することができない」らしい。([爪切りと半年前の裂きイカ]プログラミング未経験者でもできる、 Ruby を使った Twitter の bot の作り方(第一章))PR