「Microsoft TranslatorをScalaから使ってみた」から。
今回はソースそのまま(sbt用の設定は含まず)。
Translator.scala
import dispatch._, Defaults._
import scala.util.parsing.json.JSON
import java.util.Date
import scala.annotation.tailrec
object Translator {
def main(args: Array[String]) {
println("input English word")
println("'!' to quit")
@tailrec
def readToTranslate(accessTokenMessage:AccessTokenMessage):Unit = {
val line = Console.readLine("from: ")
line match {
case "!" => ()
case word if word.trim.length > 0 => {
val atm = AccessTokenMessage(Option(accessTokenMessage))
println("to: " + translate(word.trim, atm))
readToTranslate(atm)
}
case _ => {
println(">> [empty]")
readToTranslate(accessTokenMessage)
}
}
}
readToTranslate(AccessTokenMessage.empty)
}
def translate(word:String, atm:AccessTokenMessage):String = {
MicrosoftTranslator.translate(word, atm.accessToken)
}
}
object MicrosoftTranslator {
def MsTransLatorPrimaryKey = "Your Primary Key"
def MsTransLatorClientId = "Your Client Id"
def MsTransLatorClientSecret = "Your Client Secret"
def MsTransLatorUrl = "http://api.microsofttranslator.com/V2/Http.svc/Translate"
def MsTransLatorScope = "http://api.microsofttranslator.com"
def MsTransLatorAccessTokenUrl = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13"
def MsTransLatorGrantType = "client_credentials"
// Dispatch http://dispatch.databinder.net/Dispatch.html
// url(MsTransLatorAccessTokenUrl)は以下のようにも書ける。
def authSecureHost = host("datamarket.accesscontrol.windows.net").secure
def authSecureRequest = authSecureHost / "v2" / "OAuth2-13"
// 新しいアクセストークンを取得する
def newAccessTokenMessage: Map[String, String] = {
val params = Map(
"client_id" -> MsTransLatorClientId,
"client_secret" -> MsTransLatorClientSecret,
"scope" -> MsTransLatorScope,
"grant_type" -> MsTransLatorGrantType
)
val req = url(MsTransLatorAccessTokenUrl) << params
val contents = Http(req OK as.String)
val jsonResult = JSON.parseFull(contents())
jsonResult.get.asInstanceOf [Map[String, String]]
}
def translate(word:String, accessToken:String):String = {
val headerValue = "Bearer " + accessToken
val headerParams = Map("Authorization" -> headerValue)
val params = Map("text" -> word, "from" -> "en", "to" -> "ja")
val req = url(MsTransLatorUrl) <<? params <:< headerParams
val contents = Http(req OK as.xml.Elem)
contents().text
}
}
object AccessTokenMessage {
def apply(message: Option[AccessTokenMessage]):AccessTokenMessage = message match {
case Some(m) if !m.timeout => m
case _ => new AccessTokenMessage(MicrosoftTranslator.newAccessTokenMessage)
}
def empty = null
}
class AccessTokenMessage(message:Map[String, String]) {
val createTime = System.currentTimeMillis
def accessToken = message("access_token").toString
def expiresIn = message("expires_in").toLong
def timeout =
if (createTime + expiresIn * 1000 <= System.currentTimeMillis) true
else false
}