Advanced Twitter Queries with the Twitter Gem

twitter_post.pngI wanted a reliable way to find out a few things about my twitter account (for example which of the users I am following are not following me back) – unfortunately the third party apps out there are not always very reliable, do not exactly do what I want/as I want so I decided to check out how easy it is to hack up a more advanced query using a Ruby twitter API wrapper. It turned out that it couldn’t be easier!

There are several gems wrapping the Twitter API out there – I started to use the ‘twitter’ gem from John Nunemaker and I am perfectly happy with it so far. John did a great job supporting all the features offered by the API – it’s a different question that the API, like twitter itself, is quite minimalistic. For example I have not found a way to get all my followers/friends easily (drop me a comment if I am missing something) so I monkey-patched this into the module in a generic way:

module Twitter
  class Base
    def all_entries(method, options = {})
      all_entries = []  
      next_100 = self.send method, {:page => (current_page = 1)}.merge(options)
      while (next_100.size != 0) do
        all_entries << next_100
        next_100 = self.send method, {:page => (current_page += 1)}.merge(options)
      end  
      all_entries.flatten
    end
  end
end

for example you can call connection.all\_entries(:friends) to get all of your friends, given that you set up a connection to your account (I found only a method which returns your first 100 friends – didn’t spend too much time with the documentation though – agin, drop me a message if I overlooked something).

I have added a bit of syntactic sugar to be able to call connection.all\_friends instead of connection.all\_entries(:friends):

module Twitter
  class Base
    alias_method :throw_method_missing, :method_missing
    
    def method_missing(method_name, *args, &bloke)
      if (method_name.to_s =~ /^all_.+/)
        all_entries(method_name.to_s[/all_(.+)/,1], args[0] || {})
      else
        throw_method_missing(method_name, *args, &bloke)
      end
    end
  end
end

Here we ensure that only method calls that start with all\_ are handled by all\_entries, the rest is throwing a method\_missing since we are not interested in handling those messages.

Now it could not be easier to implement the function I originally intended to build: list of users who are not following back.

class Array
  def names
    self.map{|u| u.screen_name}
  end
end

module Twitter
  class Base
    def not_following_back
      all_friends.names - all_followers.names
    end
  end
end	

That’s all there’s to it (I am not a big fan of monkey patching core classes btw ; but in this case, adding the names() method to the Array class just made the method I intended to originally implement much cleaner so I rolled with it).
Note that since subtraction is a non-commutative operation, all\_friends.names – all\_followers.names is not necessarily the same as all_followers.names – all_friends.names.
This is how the final code looks like:

require 'rubygems'
require 'twitter'

connection =  Twitter::Base.new('yourname', 'yourpass')

class Array
  def names
    self.map{|u| u.screen_name}
  end
end

module Twitter
  class Base
    alias_method :throw_method_missing, :method_missing
    
    def method_missing(method_name, *args, &bloke)
      if (method_name.to_s =~ /^all_.+/)
        all_entries(method_name.to_s[/all_(.+)/,1], args[0] || {})
      else
        throw_method_missing(method_name, *args, &bloke)
      end
    end
    
    def all_entries(method, options = {})
      all_entries = []  
      next_100 = self.send method, {:page => (current_page = 1)}.merge(options)
      while (next_100.size != 0) do
        all_entries << next_100
        next_100 = self.send method, {:page => (current_page += 1)}.merge(options)
      end  
      all_entries.flatten
    end
    
    def not_following_back
      all_friends.names - all_followers.names
    end
    
  end  
end  

p connection.not_following_back

You can download/check out the code here – do not try to copy & paste it from the text as it will be b0rk3d.

In part 2 I’d like to set up a small Sinatra app showing the above users in a list – displaying their avatar, screen name and real name, plus a link to remove them if you decide so.

17 thoughts on “Advanced Twitter Queries with the Twitter Gem

  1. Nice patch. There is a relatively new API (/friends/ids/user.fmt) that lets you get all of your friends or followers in a single call but it only gives you the numeric ids so you still have to make additional calls to get any useful information. But you can use it to diff the list to narrow down what you have to get from the other calls.

    Check out http://tweepdiff.com. It’s basically the same concept in a Sinatra app. I’m not using the gem mainly because I’m using Curl::Multi and memcache to try to speed things up, but I may use it for future functionality.

    Brian

  2. Thanks for the heads up Brian :-) Seems I had to write this post to find out these possibilities.

    Of course the other goal was to show how to extend the gem with functionality that is not there.

  3. I’m pretty sure the code you’re looking for is friendids and followerids. You can get back the ids of all of your friends and followers in one query. You can do the same kind of array manipulation and then query again only on the ids you’re interested in. http://gist.github.com/71165

  4. So Twitter is awesome for Taking traffic to you website . It is very
    simple to setup and its a fun positive way to keep in contact with
    people. To get more followers on twitter check out this amazing
    tool.
    Twitter
    Traffic Machine

  5. i love to Twitter my day to day activities to my friends and followers. Twitter is much better than blogging because it is direct to the point and does not require you to type so many unnecessary words.

    1a

  6. Certainly, a plethora of people buy UniqueHoodia, as they’ve an huge craving and urge for meals, even when they are not hungry. It is designed to suppress the appetite, which means that people taking it will want to eat less.

  7. a simple leakcina oakley motions the nike jordan retro could quite possibly louis vuitthat willn coin purses leading nike air greatest extent boots ugg added rob polo regions lauren, chihuahua hairstyle these include chanel suitcases Vietnam, Louis vuitton retail outlet the karen millen countries probably true religion from air optimum southern area oakley canada lululemon chinese suppliers ocean burberry pumps promise nike rob sovereignty reebok skyscape similar new balance lauren the work grow

  8. andrew d had an idea pertaining to your quality activities in adult imitation Cartier love bracelet lifehaving said that the Kamloops Gurudwara Sahib the world want to deal a 24.4 metre excessive a flag post to obtain a christian and also its particular quadriceps and biceps motoring on Ord will be metres 11. capital city council agreed generally difference all friday. hotel room offers having some since performing. smacking the very best steadiness in the middle of ad servers along with searche

  9. Hey very cool web site!! Guy .. Excellent .. Wonderful ..
    I will bookmark your website and take the feeds also? I’m happy to find a lot of helpful information right here within the post, we want develop extra techniques
    on this regard, thank you for sharing. . . . . .

  10. Esenyurt bölgesinde hayata geçen markal? konut projelerinin baz?lar?n? sizler için derledik. ??te Esenyurt konut projeleri …
    ?ehrin h?zla geli?en bölgeleri aras?nda neredeyse ilk s?rada yer alan Esenyurt gayrimenkul sektörünün göz bebe?i olarak de?erleniyor. Aral?k ay?nda 4 bin 155 adet konutun sat???n?n gerçekle?ti?i bölgede yer alan markal? konut projelerini sizler için derledik. ??te, Esenyurt konut projeleri…

    http://www.emlakdream.com/

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>