This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 15.10, “How to create a Twitter client in Scala.”
Problem
You want to create a client to connect to Twitter to access the information you want, such as showing timelines and trends.
Solution
You could write web service client code to connect to Twitter, but the Java Twitter4J library provides an easy-to-use API that wraps the Twitter REST API. This example shows how to get information from your friend’s timelines using Twitter4J:
import twitter4j.TwitterFactory import twitter4j.Twitter import twitter4j.conf.ConfigurationBuilder object ScalaTwitterClientExample { def main(args : Array[String]) { // (1) config work to create a twitter object val cb = new ConfigurationBuilder cb.setDebugEnabled(true) .setOAuthConsumerKey("YOUR KEY HERE") .setOAuthConsumerSecret("YOUR SECRET HERE") .setOAuthAccessToken("YOUR ACCESS TOKEN") .setOAuthAccessTokenSecret("YOUR ACCESS TOKEN SECRET") val tf = new TwitterFactory(cb.build) val twitter = tf.getInstance // (2) use the twitter object to get your friend's timeline val statuses = twitter.getFriendsTimeline println("Showing friends timeline.") val it = statuses.iterator while (it.hasNext()) { val status = it.next println(status.getUser.getName + ":" + status.getText); } } }
The Twitter4J library is a custom web services library meant for interacting with the Twitter developer’s API. The library methods wrap the Twitter REST API, and because all of these methods have been created, it’s easier to use than manually writing the equivalent web service requests. The code shown here is a straight Scala port of the Java example at the Twitter4J documentation page.
The code also shows that you’ll need a series of developer tokens to work with the Twitter API. You can get those tokens at the Twitter developer website.
Discussion
As a more advanced example, the following code demonstrates how to retrieve Twitter daily trends and location trends. Besides using Twitter4J, it also uses the Akka actor library to make the calls in parallel:
import twitter4j.Twitter import akka.dispatch.{Await, Future} import akka.util.duration._ import akka.actor.ActorSystem object GetTwitterTrendsWithAkka extends TwitterBase { val propertiesFile = "/Users/Al/TwitterScripts/twitter.properties" val woeidWorld = 1 val woeidUnitedStates = 23424977 val emailSubject = "Twitter Trends" def main(args : Array[String]) { // read the properties file and create a Twitter instance populatePropertiesFromConfigFile(propertiesFile) val twitter = getTwitterInstance // get an ActorSystem in scope for the futures implicit val system = ActorSystem("TwitterFutureSystem") // make the calls in parallel using Future objects val dailyTrendsFuture = Future { getDailyTrends(twitter) } val worldFuture = Future { getLocationTrends(twitter, woeidWorld) } // wait for the calls to return before moving on val dailyTrends = Await.result(dailyTrendsFuture, 5 seconds) val worldTrends = Await.result(worldFuture, 5 seconds) println(dailyTrends) println(worldTrends) } def getDailyTrends(twitter: Twitter): String = { var sb = new StringBuilder val dailyTrends = twitter.getDailyTrends val trends = dailyTrends.get(1) for (trend <- trends.getTrends) { sb.append(trend.getName + "\n") } sb.toString } def getLocationTrends(twitter: Twitter, loc: Int): String = { var sb = new StringBuilder val locationTrends = twitter.getLocationTrends(loc) val trends = locationTrends.getTrends for (trend <- trends) { sb.append(trend.getName + "\n") } sb.toString } }
This object extends a TwitterBase
class, which is shown here:
import twitter4j.conf.ConfigurationBuilder import twitter4j.Twitter import twitter4j.TwitterFactory /** * A base class to handle Twitter setup needs. */ class TwitterBase { // twitter var consumerKey = "" var consumerSecret = "" var accessToken = "" var accessTokenSecret = "" var twitterUsername = "" // email var emailSendTo = "" var emailFrom = "" var emailSmtpHost = "" def getTwitterInstance: Twitter = { val cb = new ConfigurationBuilder() cb.setDebugEnabled(true) .setOAuthConsumerKey(consumerKey) .setOAuthConsumerSecret(consumerSecret) .setOAuthAccessToken(accessToken) .setOAuthAccessTokenSecret(accessTokenSecret) return new TwitterFactory(cb.build()).getInstance } def populatePropertiesFromConfigFile(propertiesFilename: String) { val properties = Utils.loadPropertiesFile(propertiesFilename) consumerKey = properties.getProperty("oauth.consumerKey") consumerSecret = properties.getProperty("oauth.consumerSecret") accessToken = properties.getProperty("oauth.accessToken") accessTokenSecret = properties.getProperty("oauth.accessTokenSecret") twitterUsername = properties.getProperty("twitter_username") emailSendTo = properties.getProperty("email_send_to") emailFrom = properties.getProperty("email_from") emailSmtpHost = properties.getProperty("email_smtp_host") } }
I created that base class so I could write a series of small Twitter scripts and keep my Twitter token information in a properties file. I execute those scripts using the cron
daemon on one of my Linux servers and mail the results to myself once or twice a day. I named the properties file twitter.properties, and it contains contents like this:
debug=true oauth.consumerKey=KEY1 oauth.consumerSecret=KEY2 oauth.accessToken=KEY3 oauth.accessTokenSecret=KEY4 twitter_username=YOUR_USERNAME
As shown in this file, you’ll need a series of developer tokens for these scripts to work. You can get those tokens at the Twitter developer website.
Though that may seem like a lot of code, most of it is setup work. Once the Twitter instance is configured, the work of connecting to the Twitter web service happens in these two lines of code:
val dailyTrends = twitter.getDailyTrends val locationTrends = twitter.getLocationTrends(loc)
The code also shows how to use the TwitterBase
class to handle the basic configuration. As shown in the GetTwitterTrendsWithAkka
object, you can extend this class, and then call these two lines to create a Twitter
instance:
populatePropertiesFromConfigFile(propertiesFile) val twitter = getTwitterInstance
Once you have that, use the rest of the Twitter4J library API to accomplish whatever tasks you want.
See Also
- The Twitter4J website
- The Twitter Developer website
- More discussion on making Twitter web service calls concurrently with Akka Futures
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |