By Alvin Alexander. Last updated: June 6, 2016
Without any real introduction or discussion, here's the source code for a Scala class that I use to retrieve Twitter REST content, using the Apache HttpClient library, and the Lift JSON library:
package com.devdaily.sarah.plugin.twitter import com.devdaily.sarah.plugins._ import java.io._ import net.liftweb.json._ import org.apache.http.HttpEntity import org.apache.http.HttpResponse import org.apache.http.client.ClientProtocolException import org.apache.http.client.HttpClient import org.apache.http.client.methods.HttpGet import org.apache.http.impl.client.DefaultHttpClient import scala.collection.mutable.StringBuilder import java.util.Properties import scala.collection.mutable.ListBuffer /** * Get (a) the current weather or (b) the weather forecast. */ class InteractiveTwitterClient extends SarahPlugin { val relativePropertiesFileName = "Twitter.properties" implicit val formats = DefaultFormats // for json handling val phrasesICanHandle = new ListBuffer[String]() var canonPluginDirectory = "" var trends: TwitterTrends = null // properties // val woeidWorld = 1 // val woeidUnitedStates = 23424977 val woeidKey = "woeid" var woeid = "1" // 1 == world val phraseKey = "what_you_say" var twitterPhrase = "" // sarah callback def textPhrasesICanHandle: List[String] = { return phrasesICanHandle.toList } // sarah callback override def setPluginDirectory(dir: String) { canonPluginDirectory = dir } // sarah callback def startPlugin = { populatePropertiesFromConfigFile(getCanonPropertiesFilename) println("Twitter woeid = " + woeid) println("Twitter phrase = " + twitterPhrase) } // sarah callback. handle our phrases when we get them. def handlePhrase(phrase: String): Boolean = { if (phrase.trim.equalsIgnoreCase(twitterPhrase)) { brain ! PleaseSay(getCurrentTrendsAsString) return true } else { return false } } def getCanonPropertiesFilename: String = { return canonPluginDirectory + PluginUtils.getFilepathSeparator + relativePropertiesFileName } // @see https://dev.twitter.com/docs/api/1/get/trends/%3Awoeid def getCurrentTrendsAsString: String = { try { val url = format("http://api.twitter.com/1/trends/%s.json", woeid) val content = getRestContent(url) val json = parse(content) trends = json.extract[TwitterTrends] val sb = new StringBuilder sb.append("The current Twitter trends are ") for (t <- trends.getTrends) { sb.append(format("%s, ", t.getName.replaceAll("#", ""))) } println("STRING: " + sb.toString) return splitCamelCase(sb.toString) } catch { case e: Exception => println("(TwitterPlugin) caught a plain Exception: " + e.getMessage) return("An exception happened, and I could not get the current trends.") case unknown => println("(TwitterPlugin) got an unknown exception") return("Something unknown happened, and I could not get the current trends.") } } def splitCamelCase(s: String): String = { return s.replaceAll( String.format("%s|%s|%s", "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])", "(?<=[A-Za-z])(?=[^A-Za-z])" ), " " ).replaceAll(" ", " ") } /** * TODO Move this to PluginUtils. * * Returns the text content from a REST URL. Returns a blank String if there * is a problem. */ def getRestContent(url:String): String = { val httpClient = new DefaultHttpClient() val httpResponse = httpClient.execute(new HttpGet(url)) val entity = httpResponse.getEntity() var content = "" if (entity != null) { val inputStream = entity.getContent() content = io.Source.fromInputStream(inputStream).getLines.mkString inputStream.close } httpClient.getConnectionManager().shutdown() return content } // TODO handle exceptions def populatePropertiesFromConfigFile(canonConfigFilename: String) { val properties = new Properties() val in = new FileInputStream(canonConfigFilename) properties.load(in) in.close() woeid = properties.getProperty(woeidKey) twitterPhrase = properties.getProperty(phraseKey) phrasesICanHandle += twitterPhrase } } case class TwitterLocation ( name: String, woeid: Int ) { def getName = name def getWoeid = woeid } case class TwitterTrend ( name: String, url: String, query: String ) { def getName = name def getUrl = url def getQuery = query } // model the json we get back from twitter case class TwitterTrends ( created_at: String, trends: List[TwitterTrend], as_of: String, locations: TwitterLocation ) { def getCreated_at = created_at def getTrends = trends def getAs_of = as_of def getLocations = locations }
I'll explain more of this in future Scala Twitter and REST tutorials, but for now I just want to put this code out here so I can find it easily.