Twitter is a phenomenon in the social networking space. Who would have guessed that the once-obscure site that allowed users to communicate in 140 characters or less would end up with a billion-dollar plus valuation, millions of users, hoards of applications built on top of the Twitter platform, and newer developers ever ready to jump on the bandwagon?
This article is no introduction to Twitter (it really needs none, anyway). Instead, it shows
you how to access the Twitter platform to build cool command-line applications that
are fun. Twitter is available for access from a whole host of programming languages,
including C++, Java™, Perl, Ruby, PHP, and Python.
Within each language, there is a choice of libraries or packages that do a lot of the
hard work for you. So let's get started.
This article starts out using Ruby with Twitter. You should have at lease a passing familiarity with Ruby, but even without that, it's easy enough to pick Ruby up on the go.
Several gems are available for accessing Twitter from Ruby (see Resources
for links to more information). For this article, I opted for
twitter, a Ruby wrapper by John Nunemaker. Installing
the gem is a breeze:
bash$ gem install twitter |
This command installs the Twitter client on your machine. If you have a
custom gem installation folder, then you first need to invoke
rubygems and then twitter
from your script. Here's how:
require 'rubygems' require 'twitter' |
Your very first Twitter script
That's it. Now, you're ready to build your first application, which is designed to spy on the location of your favorite people. Start by creating a script that takes in the name of the people and tells you their current location. Listing 1 below shows the code.
Listing 1. Tracking user location
require 'rubygems'
require 'twitter'
def track
ARGV.each do |name|
puts name + " => " + Twitter.user("#{name}").location
end
end
track
|
So, what's happening here? If you're new to Ruby, ARGV
is the array that gives the script access to command-line parameters. The
Twitter.user API returns a whole host of information
of which you're really only interested in the location for now. Invoking the script to
figure out the current location of Lady Gaga, Ashton Kutcher, and Oprah Winfrey
tells you what you knew anyway:
bash$ ./location_tracker.rb ladygaga aplusk Oprah ladygaga => New York, NY aplusk => Los Angeles, California Oprah => Chicago, IL |
User search with Twitter and learning authentication
Now, let's search for some specific user already in Twitter. If you can guess the user's Twitter ID, you can use the following command line:
require 'rubygems' require 'twitter' puts "User exists" if Twitter.user?(ARGV[0]) |
More often than not, however, you won't be able to guess the ID. So, something like searching for user names would be required. That brings us to the following bit of code, which searches all users whose name matches Arpan:
require 'rubygems'
require 'twitter'
names = Twitter.user_search("Arpan")
|
But this code won't work. The error log shown in Listing 2 should tell you what the problem is.
Listing 2. Oops, could not perform user search
Twitter::Unauthorized: GET https://api.twitter.com/1/users/search.json?q=Arpan%
20Sen: 401: Could not authenticate you.
from D:/Ruby/lib/ruby/gems/1.8/gems/twitter-1.6.2/lib/faraday/response/r
aise_http_4xx.rb:12:in `on_complete'
from D:/Ruby/lib/ruby/gems/1.8/gems/faraday-0.7.4/lib/faraday/response.r
b:9:in `call'
from D:/Ruby/lib/ruby/gems/1.8/gems/faraday-0.7.4/lib/faraday/response.r
b:62:in `on_complete'
|
From this code, it's clear that you first need to authenticate yourself with Twitter
before you can do anything else. This is not going to be your login/password
combination; it's your script (called an app in Twitter terminology) that
needs authentication, not you. Keeping this difference in mind, go to
http://dev.twitter.com/apps and log in with your usual
login and password. Twitter will ask for an app name, a description, and a placeholder
website for your app. After you provide this information, you should have the four
entries that help the script authenticate:
- Consumer key
- Consumer secret token
- Consumer
OAuthkey - Consumer
OAuthsecret token
Now, inside the Ruby code, you need to populate the Twitter.configure
object with these options. Listing 3 below shows the code.
Listing 3. Configuring your script for authentication
Twitter.configure do |config| config.consumer_key = "mT4atgBEKvNrrpV8GQKYnQ" config.consumer_secret = "BiQX47FXa938sySCLMxQCTHiTHjuTTRDT3v6HJD6s" config.oauth_token = "22652054-Yj6O38BSwhwTx9jnsPafhSzGhXvcvNQ" config.oauth_token_secret = "o9JuQuGxEVF3QDzMGPUQS0gmZNRECFGq12jKs" end |
Note that the entries in Listing 3 are just dummy entries; you need to populate your own in the script. With authentication out of the way, you can search for people named Arpan (see Listing 4 below).
Listing 4. Searching for people on Twitter
require 'rubygems' require 'Twitter' Twitter.configure do |config| config.consumer_key = "mT4atgBEKvNrrpV8GQKYnQ" config.consumer_secret = "BiQX47FXa938sySCLMxQCTHiTHjuTTRDT3v6HJD6s" config.oauth_token = "22652054-Yj6O38BSwhwTx9jnsPafhSzGhXvcvNQ" config.oauth_token_secret = "o9JuQuGxEVF3QDzMGPUQS0gmZNRECFGq12jKs" end users = Twitter.user_search(ARGV[0]) users.each do |user| print "\n" + user.name + " => " print user.location unless user.location.nil? end |
Now, when you save your script as search_for.rb and invoke the same on
the command line as ./search_for.rb Arpan, you would
get the names shown in Listing 5.
Listing 5. Output from the code in Listing 4
Arpan Jhaveri => New York Arpan Boddishv => Arpan Peter => Bangalore,India Arpan Podduturi => NYC Arpan Kumar De => IIT Kharagpur Arpan Shrestha => Kathmandu, Nepal Arpan Divanjee => Mumbai,India Arpan Bajaj => Bay Area, CA |
You were probably expecting a few more results. The name Arpan (which is an
Indian name) is not terribly uncommon, so what's happening? It turns out that
user_search takes an optional argument (a Ruby hash table),
and you could also specify options that would produce more results. So, modify the
code in Listing 5 slightly to pass the optional hash argument (#)
and have its values pre-populated. For example, if you want to have a single page filled
with 15 entries, you would use the code in Listing 6.
Listing 6. Displaying 15 search entries per page
require 'rubygems'
require 'twitter'
#.. authentication code here
users = Twitter.user_search(ARGV[0], {:per_page => 15})
#... same as Listing 10
|
Does this mean you can have 100 entries on a page? No, Twitter.user_search
restricts the maximum number of entries per page to 20. Listing 7
shows the code that would get you 10 pages of 20 entries each.
Listing 7. Displaying 20 entries per page
#... usual authentication stuff
pagecount = 0
while pagecount < 10
u = Twitter.user_search("#{ARGV[0]}", {:per_page => 20, :page => pagecount})
u.each do |user|
print "\n" + user.name + " => " + user.screen_name
print " => " + user.location unless user.location.nil?
end unless u.size < 20
pagecount += 1
end
|
Much better. Now that you have the users by your preferred name and their screen
names, let's move on to more interesting things. How about searching for people
named Nick who stay in New York and love Ruby? You can get the name
and location bit from user_search, but what about Ruby? That brings
us to the next thing to learn: Creating custom search clients.
Using the Twitter::Search class
You use the Twitter::Search class to create custom
search clients. Listing 8 below shows the code.
Listing 8. Learning to use the Twitter::Search class
#... user authentication
pagecount = 0
while pagecount < 10
u = Twitter.user_search("#{ARGV[0]}", {:per_page => 20, :page => pagecount})
u.each do |w|
if w.location == "New York"
results = Twitter::Search.new.from(w.screen_name).containing("ruby").fetch
puts w.screen_name if results.size > 10
end
end unless u.size < 20
pagecount += 1
end
|
What's happening here? The code begins by creating a search client using
Twitter::Search.new. Next, you ask the search
client to get all the tweets from the corresponding user that contains ruby.
Finally, the code fetch returns an array of the results, and you decide that
mentioning Ruby more than 10 times in your tweets is the way to show you love
your language.
Let's try to get an array of tweets for the hash tag #ruby.
Here's how:
#... user authentication code
results = search.hashtag("ruby").fetch
results.each do |r|
puts r.text + " from " + r.from_user
end
|
Okay, there's more to it. For a hash tag like ruby, you
expect hundreds of entries, right? This is also where using the search client comes
in handy, because you can easily retrieve the next page from the search client. The
code in Listing 9 below retrieves 10 pages of tweets on Ruby.
Listing 9. Displaying multiple pages with search
#... user authentication code
results = search.hashtag("ruby").fetch
count = 0
while count < 10
results.each do |r|
puts r.text + " from " + r.from_user
end
results = search.fetch_next_page
count += 1
end
|
The search client lets you do more cool things, like searching for tweets that are only in a specific language or originate from, say, Germany. You can even search for tweets that mention specific users or searches that match specific conditions. For example, care to search all tweets that mention Ruby but not Rails? Try this code:
search.containing("ruby").not_containing("rails").fetch
|
You can, of course, keep on cascading like thus:
search.containing("ruby").not_containing("rails").mentioning("username").from("place-id")
|
Searching for phrases is intuitive. For example, type the following code:
search.phrase("ruby on rails").fetch
|
Now, you are good to start!
While we're are at this game, here's an important piece of information that you
need to digest. It's called rate limiting, and Twitter is pretty
serious about it. Rate limiting means that Twitter lets your script make
only a limited number of queries every hour. As you have already seen, for
some types of apps you do not need explicit authentication, while for others
you do. For apps without the OAuth token, 150
calls per hour is the current maximum; for those with the token, 350 per hour
are allowed. For the latest information about Twitter policies on rate limiting,
check out Resources. To know your current limit
in your script with the authentication section, add the following line:
puts Twitter.rate_limit_status |
Here's the output:
<#Hashie::Mash hourly_limit=350 remaining_hits=350 reset_time="Sat Aug 13 21:48: 59 +0000 2011" reset_time_in_seconds=1313272139> |
If you want to be more specific, check for the following in your code:
Twitter.rate_limit.status.remaining_hits |
Incidentally, here is the output with authentication turned off. Note that you have used up 50 percent of the available limit:
<#Hashie::Mash hourly_limit=150 remaining_hits=77 reset_time="Sat Aug 13 21:13:5 0 +0000 2011" reset_time_in_seconds=1313270030> |
Updating Twitter status, retweets, and more
Enough of searching for a while. Now you need to update your Twitter status using the script. Just a one liner—that's all there is to it (of course, you do need to have the authentication code in the script):
#... authentication code Twitter.update (ARGV [0]) |
Save this code as update.rb and invoke it from the command line as
ruby update.rb "Hello World from Ruby Script". Magically,
the update is now on your Twitter page! Conversations are but a natural extension
of Twitter, and it's easy to send a direct message to another user:
#... authentication code
Twitter.direct_message_create("username", "Hi")
|
Here, you have the option of sending a message either by using the user's screen name or the numeric ID. Another interesting feature available with Twitter is that the 20 most recent messages sent by me and to me are available for a quick reference:
#... authentication code Twitter.direct_messages_sent.each do | s | puts "Sent to: " + s.recipient_screen_name puts "Text: " + s.text end |
We all want to feel important at times, and what better way than to check for other users retweeting your tweets. Here are the 20 most recent tweets being retweeted:
#... authentication code Twitter.retweets_of_me.each do |rt| print rt.text puts " retweet count = " + rt.retweet_count.to_s end |
Of course, it would be cool to know who is retweeting, but there's no direct way
to get that information from the retweets_of_me API.
Instead, you need to use the retweeters_of API. Note that
each tweet has a unique ID, and retweeters_of needs to
be passed that same ID. Listing 10 below shows the code:
Listing 10. Who's retweeting me
#... authentication code
Twitter.retweets_of_me.each do |rt|
print rt.text
print " retweeted by "
Twitter.retweeters_of(rt.id).each do |user|
puts user.screen_name
end
end
|
You can do a whole host of other things with your script. For example, say you're curious to know what's currently going on in the Twitter world. You can retrieve the top 10 trends:
Twitter.trends.each do | trend | puts trend.name end |
Incidentally, twitter.com restricts itself to report only 10 items for top trends. Refer to Resources for details. And typically, you're only interested in trends that concern your local area. Twitter can provide you with that information subject to you providing the where-on-earth ID (WOEID) and that local area having topics trending. Here's how I get what's trending for India:
Twitter.local_trends(12586534 ).each do | trend | puts trend #local_trends returns String end |
Getting the top Twitter suggested users is easy, too. Check out the script first:
Twitter.suggestions("technology").users.each do | user |
puts user.screen_name
end
|
I double-checked the output I got from this code. The fact that timoreilly made the top 10 meant that the code's working just fine. Twitter has several
categories of user interest that you can get to readily by making a call to
Twitter.suggestions (you just put
Twitter.suggestions in the script). Each category has a
short name, called slug in Twitter terminology, that you need to pass
to Twitter.suggestions to get a list of the top suggested
users. Listing 11 below shows the output.
Listing 11. Top suggested users in the technology category
gruber dannysullivan AlecJRoss timoreilly Padmasree tedtalks OpenGov twitter BBCClick woot anildash laughingsquid digiphile jennydeluxe biz ForbesTech chadfowler leolaporte |
This article ends by figuring out some of Sachin Tendulkar's (arguably the best cricketer
ever) more popular followers. To start, Sachin's ID is sachin_rt (on a
related topic, you can check his follower count with
Twitter.user("sachin_rt").follower_count and confirm his
verified status with Twitter.user("sachin_rt").verified)).
Now, use Twitter.follower_ids("sachin_rt") to get the
number of Sachin's followers. By default, you would get 5000 users, and that's
enough to get you going. Be sure to read the Twitter documentation and refer
to Twitter's API
resources for friends and followers for details on how to get the entire
follower list. Here is the code example:
#... authenticate yourself
puts Twitter.follower_ids("sachin_rt").ids.size
|
Finally, let's just sort some 50 of these 5000 users based on their
follower_count:
#... authenticate yourself
puts Twitter.follower_ids("sachin_rt").ids[0..49].sort!{|a, b| \
Twitter.user(a).followers_count <=> \
Twitter.user(b).followers_count}.reverse.first.name
|
The "!" after sort indicates
that the sort is modifying the same array on which it was invoked (and not
returning a new one), and the code within the curly brackets ({})
is the comparison function. This highlights another reason to use Ruby: What would have taken
20 lines of C++ code gets done in a single line of code
here.
Doing command-line scripting for Twitter is fun and gives you insights that are not readily available (yet) from Twitter. What's more, searching for specific individuals who fit your criteria (from local technology buffs to subject matter experts in the field) or exciting new tweets is available from the convenience of a command line. Here are two final pieces of wisdom before I sign off: Twitter is serious about the hourly rate limits, so it's a good idea to have the search results cached in your code. Second, always check out Twitter's REST API resources, which your Twitter client lists with every API. Most of all, have fun with Twitter!
Learn
-
Find Twitter libraries
for Ruby and many other languages.
-
Learn more about
OAuth-based authentication in Twitter. -
Find answers to your Twitter API questions in the
Twitter API FAQ.
-
Learn more about rate
limiting in Twitter.
-
Learn more about Twitter trends.
-
Find out more about WOEID
from the Yahoo! Developer Network.
-
AIX and UNIX developerWorks
zone: The AIX and UNIX zone provides a wealth of information relating to
all aspects of AIX systems administration and expanding your UNIX skills.
-
New to AIX and UNIX?
Visit the New to AIX and UNIX page to learn more.
-
Technology
bookstore: Browse the technology bookstore for books on this and other
technical topics.
Get products and technologies
-
Find information on the Twitter
Ruby API.
-
If you liked what you saw of Ruby in this article, check out the language's
documentation.
-
Try out IBM
software for free. Download a trial version, log into an online trial, work with
a product in a sandbox environment, or access it through the cloud. Choose from over 100 IBM product trials.
Discuss
- Follow developerWorks on Twitter.
-
Participate in developerWorks blogs and get involved in the developerWorks community.
- Get involved in the My developerWorks community.
-
Participate in the AIX and UNIX® forums:
- AIX Forum
- AIX Forum for developers
- Cluster Systems Management
- Performance Tools Forum
- Virtualization Forum
- More AIX and UNIX Forums
Arpan Sen is a lead engineer working on the development of software in the electronic design automation industry. He has worked on several flavors of UNIX, including Solaris, SunOS, HP-UX, and IRIX as well as Linux and Microsoft Windows for several years. He takes a keen interest in software performance-optimization techniques, graph theory, and parallel computing. Arpan holds a post-graduate degree in software systems. You can reach him at arpansen@gmail.com.



