RubyでTwitterのUserStreamを使う
前回紹介したRuby Twitter Gemで、ターミナルにテキストでTLを表示するクライアントを作ろうとした。最初に作ったコードは以下のような感じ。
# encoding: utf-8 require 'rubygems' require 'twitter' client = Twitter::REST::Client.new do |config| config.consumer_key = API_KEY config.consumer_secret = API_SECRET config.access_token = ACCESS_TOKEN config.access_token_secret = ACCESS_TOKEN_SECRET end mytl = client.home_timeline #TLを取得 hist = [] while 1 update = mytl - hist #前回取得したTLとの差分 num = update.length - 1 num.downto(0) do |i| id = update[i][:id] # TweetのID。ふぁぼRT等に使用 username = update[i][:user][:screen_name] # 発言者ID contents = update[i][:text] # 発言内容 str = username + ":" + contents puts str end hist = mytl sleep(90) mytl = client.home_timeline end
90秒ごとにclient.home_timelineでTLを取得し、前回取得しなかったぶんを「ID:発言内容」という形式で表示できる。client.home_timelineで取得したTLは新しいものから古いものへと順になった配列になっているため、downtoを使うことで古いものから順に表示させるようにしている。
ここで問題になったのが、APIの制限だ。このgem(以下twitter gem)ではTLを取得するたびにAPIを使用する必要があり、リアルタイムに更新しようとすると15分に15回までというTwitterのAPIの制限に簡単に達してしまう。これを避けるために更新頻度を90秒間隔に落としているが、これでは応答が遅くなってしまう。また、client.home_timelineでは一度に20件しか取得できないようなので、フォロー数の多い場合はTLの取得漏れが起きることもある。
そこで、UserStreamを使える新たなgemを使う。こちらがそれ。
tweetstream/tweetstream · GitHub
これを使って、以下のようなコードでTLの表示をリアルタイムで行うことが出来る。
# 認証 TweetStream.configure do |config| config.consumer_key = API_KEY config.consumer_secret = API_SECRET config.oauth_token = ACCESS_TOKEN config.oauth_token_secret = ACCESS_TOKEN_SECRET config.auth_method = :oauth end # TL取得 streamclient = TweetStream::Client.new streamclient.userstream do |status| username = status[:user][:screen_name] contents = status[:text] id = status[:id] str = username + ":" + contents puts str end
認証部分はtwitter gemとよく似た方法でできる。gemのサイトに使用例がいくつかあるが、streamclient.userstreamの部分を色々変更してやれば、検索やリプに即座に反応するよなbotを作成することも容易だろう。
ただし、これはあくまでUserStreamを利用してツイートを取得するだけなので、botとしてつぶやいたりふぁぼったりといった動作をするにはtwitter gemを利用する必要がある。
以下にtweetstreamとtwitter gemを利用して、起動時に過去のツイート20件を取得し表示してからUserStreamによるリアルタイム更新を行い、特定のワードに反応してリプを飛ばすクライアント兼botのようなものの例を載せる。
# encoding: utf-8 require 'rubygems' require 'twitter' require 'tweetstream' require 'reply_judge.rb' # 反応するかどうかを判定 TweetStream.configure do |config| config.consumer_key = API_KEY config.consumer_secret = API_SECRET config.oauth_token = ACCESS_TOKEN config.oauth_token_secret = ACCESS_TOKEN_SECRET config.auth_method = :oauth end normalclient = Twitter::REST::Client.new do |config| config.consumer_key = API_KEY config.consumer_secret = API_SECRET config.access_token = ACCESS_TOKEN config.access_token_secret = ACCESS_TOKEN_SECRET end puts "Configuration Success" # twitter gemで初回更新 mytl = client.home_timeline 19.downto(0) do |i| id = mytl[i][:id] username = mytl[i][:user][:screen_name] contents = mytl[i][:text] str = username + ":" + contents puts str end # tweetstream使用 streamclient = TweetStream::Client.new streamclient.userstream do |status| username = status[:user][:screen_name] contents = status[:text] id = status[:id] str = username + ":" + contents puts str if reply_judge(username,contents) != 0 time = Random.new.rand 10.0 # time = 0.1 sleep(time) str = "@" + username + " foobar" normalclient.update(str, :in_reply_to_status_id => id) # リプ先のID指定 end end