Edited at

PlayFrameworkでTwitter4Jを使ってTwitterアプリと連携をする


はじめに


概要

WeekendEngineerというグループの中で9月にPlayFrameworkを使ったTwitterツールの開発をしました。

その時に勉強した技術の一つである「PlayFrameworkでTwitter4jを使ったOauth認証とAPIの利用方法」について説明をします。

Playframework/ScalaとTwitter4jでOAuthログインするサンプルにも記事がありましたが、Play2.6に対応していないようなので、僭越ながらScala初心者がPlay2.6ver.でお送りします。

コードの全容はこちらのリポジトリにあります。

controllers.auth.AuthController


今回のプログラムで実現していること


  • Twitterアカウントでログインをする

  • ログインしたアカウントでツイートを投稿する


環境

MacOSX

Intellij

Java 10

sbt 0.13.17

scala 2.12.2

playframework 2.6.19


手順

参考→Playframework/ScalaとTwitter4jでOAuthログインするサンプル


Twitter4jプラグインを依存ライブラリに追加

今回はTwitter4jプラグインを使ってTwitterのAPIを叩きます。

以下を追記して、プラグインをインポートします。


build.sbt

// https://mvnrepository.com/artifact/org.twitter4j/twitter4j-core

libraryDependencies += "org.twitter4j" % "twitter4j-core" % "4.0.4"


Twitterアプリケーションを登録


認証用のControllerを用意

Oauthは以下のようなフローで実現されます。


  • Twitterの認証ページにリダイレクトする。

  • ユーザがTwitterアカウントでログインをする。

  • Twitterからユーザのトークンとともにアプリケーションへリダイレクトされる。

こちらで用意するのは、以下2つのアクションです。


  • Twitterの認証ページにリダイレクトする「loginアクション」

  • Twitterからのリダイレクトの受け口になる「callbackアクション」


AuthControllerクラスを作成

app>controllersにAuthControllerを作成し、

SyncCacheApiをDIします。


controllers.auth.AuthController.scala

@Singleton

class AuthController @Inject()(cc: ControllerComponents, cacheApi: SyncCacheApi) extends AbstractController(cc) {
}


loginアクションを実装


controllers.auth.AuthController.scala

def login = Action {implicit request =>

// twitter4jのtwitterインスタンスを取得
val twitter: Twitter = (new TwitterFactory()).getInstance()
// twitterからリダイレクトするURL(twitterアプリ作成時に指定したURL)を指定して、リクエストトークンを取得
val requestToken: RequestToken = twitter.getOAuthRequestToken("http://127.0.0.1:9000/callback")

// cacheにtwitterとrequestTokenを保存
cacheApi.set("twitter", twitter, 120)
cacheApi.set("requestToken", requestToken, 120)

// Twitterの認証ページにリダイレクト
Redirect(requestToken.getAuthorizationURL)
}



twitter4j.propertiesを作成

confディレクトリにtwitter4j.propertiesを作成し、twitterアプリページのkey and tokenタブにあるconsumer keyを転記します。


conf/twitter4j.properties

oauth.consumerKey=twitterアプリのAPIkey

oauth.consumerSecret=twitterアプリのAPI secret key

routesにGET /login controllers.auth.AuthController.loginを追記すれば、http://127.0.0.1/loginを叩いてTwitterの認証ページにアクセスできるはずです。


callbackアクションの作成

login時に保存したrequestTokenとtwitterからのリクエストに保存されたoauthVerifierを使用して、ユーザのアクセストークンを取得しています。


controllers.auth.AuthController.scala

def twitterOAuthCallback = Action { implicit request =>

// TwitterのオブジェクトをCacheから取得
val getTwitter : Option[Twitter] = Option(cacheApi.get("twitter"))

// 取得できない場合はトップ画面へ
getTwitter match {
case Some(twitter) => {
// RequestTokenのオブジェクトをCacheから取得
val getRequestToken: Option[RequestToken] = Option(cacheApi.get("requestToken"))

// 取得できない場合はトップ画面へ
getRequestToken match {
case Some(requestToken) => {

// authVerifierを取得する
var authVerifier: String = request.queryString.get("oauth_verifier").get.head

// AccessTokenを取得する
val accessToken: AccessToken = twitter.getOAuthAccessToken(requestToken, authVerifier)
cacheApi.set("accessToken", accessToken, 4320)

// Twitterオブジェクトの認証
twitter.verifyCredentials()

// Cacheに認証情報を保存(私はTwitterSessionクラスのインスタンスを生成し、保存しました。)
val twitterSession: TwitterSession =
new TwitterSession(accessToken.getToken, accessToken.getTokenSecret, accessToken.getScreenName)
cacheApi.set("twitterSession", twitterSession, 4320)

// 不要なのでCacheから削除
cacheApi.remove("twitter")
cacheApi.remove("requestToken")

}
case _ =>
}
}
case _ =>
}
Redirect("/")
}


routesにGET /callback controllers.auth.AuthController.callbackを追記すれば、Oauthログインができているはずです。


APIを使用する

Twitterクラスのインスタンスを生成するときに、Oauthで取得したAccessTokenを突っ込むだけで、TwitterAPIを使えます。以下の例はツイートを投稿するUpdateStatusというメソッドを使っている例です。


client.Twitter4JClient.scala

@Singleton

class Twitter4JClient{
/**
* TweetをPostする.
* @param accessToken
* @param tweetText
* @throws TwitterException
* @return
*/

def updateStatus(token: String, secret: String, tweet: Tweet): Tweet = {
val accessToken: AccessToken = new AccessToken(token, secret)
val twitter: Twitter = (new TwitterFactory()).getInstance(accessToken)
try {
val status: Status = twitter.updateStatus(tweet.getBody())
return Tweet(status.getText, status.getUser.getScreenName)
} catch {
case e:TwitterException => throw e
}
}
}


参考URL

Playframework/ScalaとTwitter4jでOAuthログインするサンプル