I have a 19" monitor on the counter between my kitchen and living room, and it’s powered by a Raspberry Pi. I use the Linux Phosphor screen saver to show a scrolling “news and stock ticker” on the display, which I’ve programmed to show news from several different sources (Atom and Rss feeds, along with other news and data sources). An old version of the display looks like this:
Today I added a new “Word of the day” feature to the display, and as with all of the other code, I wrote a Scala shell script to generate the output.
My Scala “Word of the day” script
Here’s the Scala 2 shell script I wrote to get and print the word of the day from the merriam-webster.com website:
#!/bin/sh exec scala -savecompiled -classpath "lib/AtomReaderLibrary-assembly-1.0.jar" "$0" "$@" !# import java.net.{URL, URLConnection} import com.rometools.rome.feed.synd.{SyndEntry, SyndFeed} import com.rometools.rome.io.{SyndFeedInput, XmlReader} import org.jsoup.Jsoup import org.jsoup.nodes.Document import com.alvinalexander.atom.JsoupFormatter import scala.util.{Try,Success,Failure} import scala.collection.JavaConverters._ // read the desired feed with ROME val syndFeed: Try[SyndFeed] = Try { val urlConnection = getUrlConnection("https://www.merriam-webster.com/wotd/feed/rss2") val xmlReader = new XmlReader(urlConnection) val syndFeedInput = new SyndFeedInput syndFeedInput.build(xmlReader) } syndFeed match { case Success(feed) => { // convert it to a Scala `Seq` val entries: Seq[SyndEntry] = asScalaBuffer(feed.getEntries).toVector // the first entry is today's word of the day val entry: SyndEntry = entries(0) // print the word in a formatted way println(getWordFormatted(getWordOfDay(entry))) // start getting the description (which is the meaning of the word) val descriptionAsHtml = entry.getDescription.getValue // clean up the html with Jsoup val jsoupDocument: Document = Jsoup.parse(descriptionAsHtml) // remove all anchor tags from the document jsoupDocument.select("a").remove() // use this special formatter so the output is on multiple lines. // the default formatter prints everything on one long line. val jsoupFormatter = new JsoupFormatter val documentAsPlainText = jsoupFormatter.getPlainText(jsoupDocument) val finalCleanedDescription = documentAsPlainText.replaceAll("\n\n", "\n").trim println(finalCleanedDescription) } case Failure(e) => { println("\nCould not get the word of the day. Reason follows.") println(s"${e.getMessage}\n") } } def getUrlConnection(url: String): URLConnection = { val urlConnection = new URL(url).openConnection urlConnection.setConnectTimeout(5000) urlConnection.setReadTimeout(5000) urlConnection } def getWordOfDay(entry: SyndEntry): String = entry.getTitle.toUpperCase def getWordFormatted(s: String): String = { s""" | |Word of the Day |--------------- |Word: $s """.stripMargin }
The code needs some cleanup/refactoring, but basically what it does is call the Merriam-Webster URL, then extracts the word of the day from its output.
The “Word of the day” output
Here’s what the output from that Scala script looks like on January 28, 2018:
Word of the Day
---------------
Word: POPINJAY
Merriam-Webster's Word of the Day for January 28, 2018 is:
popinjay \PAH-pin-jay\ noun
: a strutting person
Examples:
"Who does that guy think he is?" Amanda asked in regard to the popinjay who
strolled into the restaurant demanding to be seated instantly.
"[Ryan] Gosling plays the motormouthed popinjay, a tough talker who's actually
quite skittish about his bloody job." — Sean P. Means,The Salt Lake Tribune, 23
May 2016
Did you know?
Popinjays and parrots are birds of a feather. Popinjay, from the Middle French
wordpapegai, is the original name for a parrot in English. The French word, in
turn, came from the Arabic word for the bird,babghā’. , which English speakers
adopted later, is probably a modification of the Middle Frenchperroquet, which
is also the source of the English. In the days of Middle English, parrots were
rare and exotic, and it was quite a compliment to be called apopinjay after
such a beautiful bird. But by the 1500s, parrots had become more commonplace,
and their gaudy plumage and vulgar mimicry helpedpopinjay develop the
pejorative sense we use today.
Discussion
I’ve written about Scala shell scripts before, so I won’t say too much about this script. A few important notes are:
- It uses the ROME and Jsoup libraries
- The
JsoupFormatter
comes from my AtomRssReaderLibrary project (if I remember right, it’s just a copy of the Java class of the same name you can find on the internet) - I use the Scala
JavaConverters
class to convert a JavaList
into a ScalaVector
- As usual, I could condense the code, but I try to write code like this in an “obvious” style that’s easy to support/update/understand in the future
- I named my Scala shell script GetWordOfTheDay.sh, and I call it with a Linux crontab entry, and redirect its output so the Phosphor screen saver can read it
- There are a few problems with the output where words that are italicized or included in anchor tags run together, but I haven’t looked into those issues yet
In summary, if you wanted to see how to get the “Word of the day” from an Atom or RSS feed like Merriam-Webster’s, or wanted to see an example of a Scala shell script, I hope this example is helpful.