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でテストして動作確認しています。