I've analysed the difference between the python example on the rdio page, and what Scala does.
I think there are really two problems.
The first is that you need to obtain an access token.
The second issue is that clearly the sign method of dispatch library makes rdio unhappy. It removes trailing slashes, which makes the signature not to match.
The first problem, is quite easy to solve - you just have to use Exchange class, which will do most of the work for you.
The second problem was quite tricky, I've just copied the original sign
method and altered the part, which was removing a trailing slash.
The code is below.
val ck = new ConsumerKey("YOUR_CONSUMER_KEY", "YOUR_CONSUMER_TOKEN")
// declare exchange to obtain an access token
val exchange = new Exchange with SomeHttp with SomeCallback with SomeConsumer with SomeEndpoints {
override def http: HttpExecutor = Http
override def callback: String = "oob"
override def consumer: ConsumerKey = ck
override def accessToken: String = "http://api.rdio.com/oauth/access_token"
override def authorize: String = "http://api.rdio.com/oauth/authorize"
override def requestToken: String = "http://api.rdio.com/oauth/request_token"
}
/// we change the default method of the dispatch
def sign(request: Req, consumer: ConsumerKey, token: RequestToken): Req = {
val calc = new OAuthSignatureCalculator(consumer, token)
request underlying { r =>
val req = r.build
//!!! here we make change so the trailing slash is not removed
val baseurl = req.getURI.toString.takeWhile(_ != '?').mkString("")
calc.calculateAndAddSignature(baseurl, req, r)
r
}
}
val response = exchange.fetchRequestToken.right.flatMap { rt =>
// point your browser to this URL with the given oauth token, we'll get PIN back
println(s"Go to https://www.rdio.com/oauth/authorize/?oauth_callback=oob&oauth_token=${rt.getKey}")
print("Enter PIN:")
val pin = readLine()
exchange.fetchAccessToken(rt, pin)
}.right.flatMap { at =>
// now we can call API using the consumer key and the access token
val request = sign(url("http://api.rdio.com/1/").POST << Map("method" -> "currentUser"), ck, at)
val response = Http(request > as.String)
response.map(Right(_))
}
response.map { responseOrError =>
responseOrError.fold(err => println(s"Error $err"), suc => println(s"Response: $suc"))
Http.shutdown()
}