我已经分析了 rdio 页面上的 python 示例和 Scala 所做的区别。
我觉得真的有两个问题。
首先是您需要获取访问令牌。
第二个问题显然是 dispatch 库的 sign 方法让 rdio 不高兴。它删除了尾部斜杠,这使得签名不匹配。
第一个问题很容易解决——您只需要使用 Exchange 类,它将为您完成大部分工作。
第二个问题非常棘手,我刚刚复制了原始sign
方法并更改了删除尾部斜杠的部分。
代码如下。
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()
}