ゆうなんとかさんの雑記帳的な。

Twitterで踊ったり音ゲーしたりしてるあの名前がよくわからない人が書いてるらしいよ。

EventMachineのつかいかたのはずだったけどStreamingするAPIの説明とか簡単なリプライbotの作り方とかになった

ServerSentEventを使って何かやってみたいなと思っていたのですが、結局TwitterのタイムラインをStreaming APIで読み取って、適当にリプライを返すbotになってしまいました。

Steaming APIの仕様

curlで読み取ってみるとこうなります。

 curl --get 'https://userstream.twitter.com/1.1/user.json' --header 'Authorization: OAuth oauth_consumer_key="OauthConsumerKey", oauth_nonce="OauthNonce", oauth_signature="OauthSignature", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1388583567", oauth_token="OauthToken", oauth_version="1.0"' --verbose
* Adding handle: conn: 0x000000000000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x000000000000) send_pipe: 1, recv_pipe: 0
* About to connect() to userstream.twitter.com port 443 (#0)
*   Trying 199.59.148.139...
* Connected to userstream.twitter.com (199.59.148.139) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_RC4_128_SHA
* Server certificate: userstream.twitter.com
* Server certificate: VeriSign Class 3 Secure Server CA - G3
> GET /1.1/user.json HTTP/1.1
> User-Agent: curl/7.30.0
> Host: userstream.twitter.com
> Accept: */*
> Authorization: OAuth oauth_consumer_key="OauthConsumerKey", oauth_nonce="OauthNonce", oauth_signature="OauthSignature", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1388583567", oauth_token="OauthToken", oauth_version="1.0"
> 
< HTTP/1.1 200 OK
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: application/json
< Date: Wed, 01 Jan 2014 13:39:57 GMT
< 
{"friends":[ ... ]}

{"created_at":"Wed Jan 01 13:40:01 +0000 2014", ... }
{"created_at":"Wed Jan 01 13:40:02 +0000 2014", ... }

{"created_at":"Wed Jan 01 13:40:05 +0000 2014", ... }
{"created_at":"Wed Jan 01 13:40:08 +0000 2014", ... }

...

改行2つで区切られたものがデータのひとかたまりです。これが一度に投げてこられるわけですね。コネクションを張り続けている間、ずっとこういうデータが流れ続けてきます。これをEventMachineでいい感じにキャッチして、なんかしてみようというつもりだったのですが、よくわからないところではまってしまって無理でした。

結局リプライbotを作ってみた

結局、裏でStreaming APIを捌いているGemを見つけて、それでリプライが来たらなんかtweetするような感じのbotを動かせるようにしてみました。その前に試行錯誤と再三のフルスクラッチがありますが、だいたい30分くらいでできました。細かいところでつまずいて試行錯誤した割にはコードが短いので、Rubyの闇さと先人の偉大さが改めてわかりました。

require 'tweetstream'
require 'twitter_oauth'

CONSUMER_KEY = 'CONSUMER_KEY'
CONSUMER_SECRET = 'CONSUMER_SECRET'
OAUTH_TOKEN ||= 'OAUTH_TOKEN'
OAUTH_TOKEN_SECRET ||= 'OAUTH_TOKEN_SECRET'

def client
  TwitterOAuth::Client.new(
    consumer_key: CONSUMER_KEY,
    consumer_secret: CONSUMER_SECRET,
    token: OAUTH_TOKEN,
    secret: OAUTH_TOKEN_SECRET
  )
end

TweetStream.configure do |config|
  config.consumer_key       = CONSUMER_KEY
  config.consumer_secret    = CONSUMER_SECRET
  config.oauth_token        = OAUTH_TOKEN
  config.oauth_token_secret = OAUTH_TOKEN_SECRET
  config.auth_method        = :oauth
end

TweetStream::Client.new.userstream do |status|
  if status.text.to_s[/^@yuu_hara/]
    begin
      tweet = "@#{status.user.screen_name} にゃーん"
      p client.update tweet if client.authorized?
    rescue Exception => e
      p e
    end
  end
end

なんでこう細かいところではまりやすいのか、理由がわからないと今後苦労しそうですね…それはさておき、今年もよろしくお願いします。