icleversoft
10/12/2012 - 11:20 AM

EventMachine

EventMachine

<!DOCTYPE html>
<head>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
  <script type="text/javascript">
    $(document).ready(function() {
      var container = $('.container');
      
      var addTweetToPage = function(language, tweet) {
        var id = 'tweet' + language;
        if ($('#'+id).length == 0) {
          container.append('<div id="'+id+'"><h1>'+language+'</h1></div>')
        }
        $('#'+id).append('<div class="tweet">'+tweet+'</div>');
      };
      
      var socket = new WebSocket('ws://0.0.0.0:8080/');

      socket.onopen = function() {
        console.log("Socket opened");
      };

      socket.onmessage = function(message) {
        var info = JSON.parse(message.data);
        console.log(info.lang, info.tweet);
        addTweetToPage(info.lang, info.tweet);
      };

      socket.onclose = function() {
        console.log("Socket closed");
      };
    })
  </script>
</head>

<body>
  <div class="container"></div>
</body>
require 'em-http'
require 'json'

class TwitterStream
  URL = 'http://stream.twitter.com/1/statuses/filter.json'
  
  def initialize(username, password, term)
    @username, @password = username, password
    @term = term
    @callbacks = []
    @buffer = ""
    listen
  end
  
  def ontweet(&block)
    @callbacks << block
  end
  
  private
  
  def listen
    http = EventMachine::HttpRequest.new(URL).post({
      :head => { 'Authorization' => [@username, @password] },
      :query => { "track" => @term }
    })
    
    http.stream do |chunk|
      @buffer += chunk
      process_buffer
    end
  end
  
  def process_buffer
    while line = @buffer.slice!(/.+\r\n/)
      tweet = JSON.parse(line)

      @callbacks.each { |c| c.call(tweet['text']) }
    end
  end
end
require 'rubygems'
require 'eventmachine'
require 'em-websocket'
require 'twitter_stream'
require 'language_detector'

TWITTER_USERNAME = ''
TWITTER_PASSWORD = ''
TWITTER_TERM = 'twitter'

EM.run {
  websocket_connections = []
  
  EM::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws|
    ws.onopen {
      puts "Websocket connection opened"
      websocket_connections << ws
    }
    ws.onclose {
      puts "Websocket connection closed"
      websocket_connections.delete(ws)
    }
  end
  
  stream = TwitterStream.new(TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_TERM)
  stream.ontweet { |tweet|
    LanguageDetector.new(tweet).callback { |lang|
      puts "New tweet in #{lang}: #{tweet}"
      
      websocket_connections.each do |socket|
        socket.send(JSON.generate({
          :lang => lang,
          :tweet => tweet
        }))
      end
    }
  }
}
require 'em-http'
require 'json'

class LanguageDetector
  URL = "http://www.google.com/uds/GlangDetect"
  
  include EM::Deferrable
  
  def initialize(text)
    request = EM::HttpRequest.new(URL).get({
      :query => {:v => "1.0", :q => text}
    })
    
    # This is called if the request completes successfully (whatever the code)
    request.callback {
      begin
        if request.response_header.status == 200
          info = JSON.parse(request.response)["responseData"]
          if info['isReliable']
            self.succeed(info['language'])
          else
            self.fail("Language could not be reliably determined")
          end
        else
          self.fail("Call to fetch language failed")
        end
      rescue
        puts request.response
        self.fail
      end
    }
    
    # This is called if the request totally failed
    request.errback {
      self.fail("Error making API call")
    }
  end
end

Getting started

First add your twitter username and password. Then server.rb and once it's started open websocket.html in your browser. You should see some tweets appear. If not take a look at the javascript console.