読者です 読者をやめる 読者になる 読者になる

Twitter User Streamsをいじる

User Streamsをいじるというとtwitter-amqp-websocket系のサンプルが世の中にたくさんあふれていたので自分でもいじってみる。Rubyもいまいちよくわかっていないのでこの書き方でいいのかよくわからないのだけど、とりあえず動いているし止まるので問題ないのだろう。
まずは、User Streamを取り出してAMQPに突っ込むところ。ruby-amqpはEventMachineというのを使っているらしいんだけどこんな感じでいいんだろうか!?

#!/usr/bin/env ruby
# coding: utf-8

#<http://blog.0x82.com/2009/12/28/twitter-amqp-websocket-example-no-polling>
#<http://d.hatena.ne.jp/shibason/20090802/1249204953>
#<http://github.com/ruby-amqp/amqp>
#<http://dev.twitter.com/pages/user_streams>

require 'rubygems'
require 'amqp'
require 'twitter/json_stream'

Signal.trap('INT') { AMQP.stop { EM.stop } }
AMQP.start(:host => 'localhost', :logging => false) do |connection|
  # default is to connecto to localhost:5276, to root("/") vhost as guest/guest
  puts "Connected to AMQP broker. Running #{AMQP::VERSION} version of the gem ..."
  channel = AMQP::Channel.new(connection)
  twitter = channel.fanout('twitter')

  stream = Twitter::JSONStream.connect(
    :path => '/2/user.json',
    :host => 'userstream.twitter.com',
    :ssl  => true,
    :oauth => {
      :consumer_key => '__CONSUMER_KEY__',
      :consumer_secret => '__CONSUMER_SECRET__',
      :access_key => '__ACCESS_KEY__',
      :access_secret => '__ACCESS_SECRET__',
    }
  )

  stream.each_item do |status|
    twitter.publish(status)
  end

  stream.on_error do |message|
    $stdout.print "error: #{message}\n"
    $stdout.flush
  end

end


AMQPに流し込むことができればあとは取り出さないと意味がないのでまずは表示するところから。

#!/usr/bin/env ruby

require 'rubygems'
require 'uuid'
require 'bunny'
require 'json' if RUBY_VERSION < '1.9.0'

# <https://github.com/ruby-amqp/bunny>
Signal.trap('INT'){ exit! }
uuid = UUID.new
b = Bunny.new(:logging => false)
b.start
q = b.queue(uuid.generate)
q.bind('twitter')
q.subscribe(:ack => false) do |msg|
  begin
    d = JSON.parse(msg[:payload])
    if d['text']
      u = d['user']
      puts "#{u['screen_name']}: #{d['text']}"
    end
  rescue
    break
  end
end
b.stop


表示するところまでできてしまえばあとは使い方をどう広げられるかが問題になる。あんちょくなのはJabber経由で通知するとか。

#!/usr/bin/env ruby
# config: utf-8

require 'rubygems'
require 'uuid'
require 'bunny'
require 'json' if RUBY_VERSION < '1.9.0'
require 'xmpp4r-simple'

Signal.trap('INT'){ exit! }
im = Jabber::Simple.new("user@example.com", "__PASSWORD__")
uuid = UUID.new
b = Bunny.new(:logging => false)
b.start
q = b.queue(uuid.generate)
q.bind('twitter')
q.subscribe do |msg|
  begin
    d = JSON.parse(msg[:payload])
    if d['text']
      u = d['user']
      im.deliver( "friend@example.com",
                  "#{u['screen_name']}: #{d['text']}")
    end
  rescue
    break
  end
end
b.stop

Ubuntu 10.10にruby 1.8.7, rabbitmq-server 2.4.1-1, ejabberd 2.1.5-2でテストして動作確認しています。