Search code examples
rubymongodbubuntutweetstream

Ruby Tweetstream MongoDB Error


I keep getting the following error when running the following ruby script. If anyone can help me fix this it would be greatly appreciated. I've removed any sensitive data such as API keys.

Code:

#!/usr/bin/env ruby
require "tweetstream"
require "mongo"
require "time"

TweetStream.configure do |config|
  config.consumer_key       = 'KEY'
  config.consumer_secret    = 'SECRET'
  config.oauth_token        = 'TOKEN'
  config.oauth_token_secret = 'TOKEN_SECRET'
  config.auth_method        = :oauth
end

db = Mongo::Connection.new("ds045037.mongolab.com", 45037).db("tweets")
auth = db.authenticate("DB_USERNAME", "DB_PASSWORD")
tweets = db.collection("tweetdata")

TweetStream::Daemon.new("TWITTER_USERNAME", "TWITTER_PASSWORD").track("TERM") do |status|
  # Do things when nothing's wrong
  data = {"created_at" => Time.parse(status.created_at), "text" => status.text, "geo" => status.geo, "coordinates" => status.coordinates, "id" => status.id, "id_str" => status.id_str}
  tweets.insert({"data" => data});
end

Command to start the script:

ruby tweetscrape.rb

Ruby version:

ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-linux]

ruby -c tweetscrape.rb produces:

Syntax OK

Error Message:

/usr/local/rvm/gems/ruby-1.9.3-p429/gems/daemons-1.1.9/lib/daemons.rb:184:in `[]=': can't convert Symbol into Integer (TypeError)
    from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/daemons-1.1.9/lib/daemons.rb:184:in `run_proc'
    from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/daemon.rb:48:in `start'
    from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/client.rb:131:in `filter'
    from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/client.rb:98:in `track'
    from tweetscrape.rb:19:in `<main>'

EDIT: I now have no errors using the below but nothing is entered in to the mongodb:

#!/usr/bin/env ruby
require "tweetstream"
require "mongo"
require "time"

TweetStream.configure do |config|
  config.consumer_key       = 'gfdsgfdsgfdsgfdsgfdsgfds'
  config.consumer_secret    = 'gfsdgfdsgfdsgfdsgfsdgfd'
  config.oauth_token        = 'gfdgfdsgfsdgfdsgfsdgf'
  config.oauth_token_secret = 'hsgfsdgfsdgfsdgfds'
  config.auth_method        = :oauth
end

db = Mongo::Connection.new("ds045037.mongolab.com", 45037).db("tweets")
auth = db.authenticate("gfsdgfdsgfsd", "gfdsgfdsgfdsgfsd")
tweets = db.collection("tweetdata")

TweetStream::Client.new.track('TERM') do |status|
  puts status.text
  data = {"created_at" => Time.parse(status.created_at), "text" => status.text, "geo" => status.geo, "coordinates" => status.coordinates, "id" => status.id, "id_str" => status.id_str}
  tweets.insert({"data" => data})
end

Tweets show on screen through puts though...


Solution

  • The initial error you were getting with the Daemon class is because you're not passing the correct parameters to the constructor. The contructor takes a string and a hash.

    Moving on from that , the insert failed because:

    1. parsing status.datetime throws an exception (its already a Time object).
    2. status.coordinate throws an exception if there's no coordinate.

    The following code works for me (note : I added growl so you can see the tweets):

    #!/usr/bin/env ruby
    require "tweetstream"
    require "mongo"
    require "time"
    require 'growl'
    
    DESIRED = %w{created_at text geo coordinates id id_str}
    host= ENV["MONGO_HOST"]  || 'localhost'
    port = ENV["MONGO_PORT"]  || 27017
    username = ENV["MONGO_USERNAME"]
    password = ENV["MONGO_PASSWORD"]
    
    term = ARGV[1] || 'TERM'
    
    begin
      TweetStream.configure do |config|
        config.consumer_key       = ENV["TWEET_CONSUMER_KEY"]
        config.consumer_secret    = ENV["TWEET_CONSUMER_SECRET"]
        config.oauth_token        = ENV["TWEET_OAUTH_TOKEN"]
        config.oauth_token_secret = ENV["TWEET_OAUTH_TOKEN_SECRET"]
        config.auth_method        = :oauth
      end
    
      db = Mongo::Connection.new(host, port).db("tweets")
      db.authenticate(username, password)
      tweets = db.collection("tweetdata")
    
      puts "about to start tracking term #{term}"
      TweetStream::Daemon.new('tracker').track(term) do |status|
        Growl.notify status.text, :title => status.user.screen_name
    
        #
        # filter out nil values
        # filter out all keys not in the desired array
        #
        data = status.attrs.select{|k,v| !v.nil? && DESIRED.include?(k.to_s)}
        tweets.insert({"data" => data});
      end
    
    rescue Mongo::ConnectionFailure
      puts "Connection Error :  #{$!}"
    rescue Mongo::AuthenticationError
      puts "Auth Error :  #{$!}"
    rescue Mongo::MongoDBError
      puts "Unexpected Error :  #{$!}"
    end
    

    You'll need to setup your environment with the following correct values :

    export MONGO_USERNAME="..."
    export MONGO_PASSWORD="..."
    export TWEET_CONSUMER_KEY="..."
    export TWEET_CONSUMER_SECRET="..."
    export TWEET_OAUTH_TOKEN="..."
    export TWEET_OAUTH_TOKEN_SECRET="..."
    

    Then you can start the daemon with something like (in this case we'll search for yankees):

    ruby tweetscrape.rb start yankees