revelフレームワークを使ってTwitterAPIを叩く!
golangのフレームワークrevelを使用してTwitterAPIを叩きます。
アプリケーションの作成
revelフレームワークでまずはアプリケーションを作成しましょう!
$ revel new twitterApp
そうすると$GOPAT/src/twitterAppが作成されるはずです。
※ revelフレームワークの導入はこちらから。
revelフレームワークを入れてみる - umegusa's blog
Routingの設定
まずはルーティングを設定します。
今回はこのように設定しました。
$GOPATH/src/twitterApp/conf/route
GET / App.Index GET /auth Auth.Index GET /auth/callback Auth.Callback GET /show Show.Index
動きとしては、
URL | 動作 |
---|---|
http://host/ | AppコントローラのIndexアクションメソッドを呼び出す |
http://host/auth/ | AuthコントローラのIndexアクションメソッドを呼び出す |
http://host/auth/callback/ | AuthコントローラのCallbackアクションメソッドを呼び出す |
http://host/show/ | ShowコントローラのIndexアクションメソッドを呼び出す |
こんな感じに設定します。
それではコントローラをいじってみましょう。
$GOPAT/src/twitterApp/app/controller/app.go
package controllers import "github.com/revel/revel" type App struct { *revel.Controller } func (c App) Index() revel.Result { return c.Render()
/でアクセスするとこちらのIndex()メソッドが呼び出されます。
返り値としてはrevel.Resultを返します。
returnで返しているのは、views下のhtmlファイルを返します。
この場合、$GOPAT/src/twitterApp/app/views/App/Index.html を返します。
基本的に$GOPAT/src/twitterApp/app/views/{コントローラ名}/{アクションメソッド名}.html を返すみたいですよ。
中のHTMLは標準を少しだけいじりました。
Index.html
<div class="container"> <div class="row"> <div class="hero-text"> <h1>Twitter認証するよ!!</h1> <p><a href="/auth/">Twitterで認証するよ!</a></p> </div> </div> </div>
実行してみる
とりあえず実行するとこんな感じです。
実行方法は下記のように行います。
$ revel run twitterApp
画面だとこんな感じです。
http://localhost:9000/
$GOPATH/src/twitterApp/conf/app.conf下をいじっていなければ9000番のポートで実行できるはずです。
続いてOAuth認証を実装してみましょう。
oauth認証をする
TwitterのOAuthのバージョンは1.0で、それを簡単にしてくれるライブラリを使用します。
それがこちらです。
mrjones/oauth · GitHub
実際に使用する前にまずはクライアントアプリケーションを登録し、consumerkey, consumersecretを取得する必要があります。
クライアントの登録は下記のページから作成できます。
Twitter Application Management
作成した際は必ずCallback URLを必ず設定してください。(設定しないとoauth_callbackパラメータが無効になり、コールバックが無効になってしまいます)
値はURLの形であれば適当で問題ありません(ex: http://twitter.com/kaisou4537/)
では実際に使ってみます。
controller下にauthコントローラを作成します。
auth.go
package controllers import ( "encoding/json" "github.com/mrjones/oauth" "github.com/revel/revel" "twitterApp/app/models" ) type Auth struct { *revel.Controller } // oauthのコンシューマ設定 var twitter = oauth.NewConsumer( // 先ほど取得したキーを使用する "consumerkey", "consumersecret", oauth.ServiceProvider{ AuthorizeTokenUrl: "https://api.twitter.com/oauth/authorize", RequestTokenUrl: "https://api.twitter.com/oauth/request_token", AccessTokenUrl: "https://api.twitter.com/oauth/access_token", }, ) func (c Auth) Index() revel.Result { // Twitterから情報を取得する user := getUser() // callback URLを設定する requestToken, url, err := twitter.GetRequestTokenAndUrl("http://localhost:9000/auth/callback") if err == nil { // ユーザ情報セット user.RequestToken = requestToken // oauth_verifierを取得 return c.Redirect(url) } revel.ERROR.Println("リクエストトークン取得できませんでした!!", err) return c.Render() } func (c Auth) Callback(oauth_verifier string) revel.Result { // セットしたユーザ情報取得 user := getUser() // access_tokenを獲得 accessToken, err := twitter.AuthorizeToken(user.RequestToken, oauth_verifier) if err == nil { // ユーザ情報を取得する resp, _ := twitter.Get( "https://api.twitter.com/1.1/account/verify_credentials.json", map[string]string{}, accessToken, ) defer resp.Body.Close() account := struct { Name string `json:"name"` ProfileImageURL string `json:"profile_image_url"` }{} _ = json.NewDecoder(resp.Body).Decode(&account) // 表示用情報をセット setUserData(account.Name, account.ProfileImageURL) } else { // 失敗 revel.ERROR.Println("取得失敗!!", err) } return c.Redirect(Show.Index) } func (c Auth) Show() revel.Result { // ユーザ情報取得 user := getShowUser("kaisou_test") return c.Render(user) } // Twitterユーザ情報 func getUser() *models.User { return models.FindOrCreate("kaisou") } // 表示用ユーザ情報セット func setUserData(name, imgURL string) { models.CreateShowUser(name, imgURL) }
~/app/models 下に下記の二つのファイルも作成します。
userinfo.go
package models import "github.com/mrjones/oauth" // Twitter用ユーザ情報 type User struct { Username string RequestToken *oauth.RequestToken AccessToken *oauth.AccessToken } var db = make(map[string]*User) func FindOrCreate(username string) *User { if user, ok := db[username]; ok { return user } user := &User{Username: username} db[username] = user return user }
showuser.go
package models // 表示用ユーザ情報 type ShowUser struct { Username string ImgURL string } var dbShowUser = make(map[string]*ShowUser) func CreateShowUser(name, imgURL string) { user := &ShowUser{Username: name, ImgURL: imgURL} dbShowUser[name] = user } func FindShowUser(name string) *ShowUser { if user, ok := dbShowUser[name]; ok { return user } else { return nil } }
auth.goでは、まずリクエストトークンを取得します。
その後、設定したコールバックURLにアクセスさせ、アクセストークンを取得、成功したらAPIをたたくという流れになります。
auth.goで取得したデータをリクエストトークンを格納、アクセストークンを取得するのに必要になります。
そして、アクセストークンを使用して取得したTwitterの情報をshowuser.goに格納し、View側のHTMLに渡してあげます。
auth.goのCallbackメソッドの最後にShowコントローラのIndexアクションメソッドにリダイレクトしていますね。
show.goは下記のようになっています。
package controllers import ( "github.com/revel/revel" "twitterApp/app/models" ) type Show struct { *revel.Controller } func (c Show) Index() revel.Result { // ユーザ情報取得 user := getShowUser("kaisou_test") return c.Render(user) } // 表示用ユーザ情報取得 func getShowUser(name string) *models.ShowUser { return models.FindShowUser(name) }
auth.goで格納した情報を取得し、Viewに渡しています。
プログラムで処理した後のViewの値はRenderメソッドに渡してあげることでViewで扱えるようになります。
尚、使用する場合は下記のように呼び出します。
~/app/views/Show/Index.html
<div> <img src="{{.user.ImgURL}}"> <p>{{.user.Username}}</p> <p>めっちゃ小さいけどとれてるね!!!!!</p> </div>
実行して表示してみると画像のようになります。
ユーザ情報が取得され、表示されているのが分かりますね!
これでTwitterAPIをたたいてユーザ情報を取得することができました!
終わりに
こんなにめんどくさいことしなくてもDBにaccesstoken格納してAPI呼び出せるようにしとけばええやん、という突っ込みは今回はなしでお願いします。。
とりあえずテスト的に取ることができました、ぱちぱち。
APIにアクセスして値を取ることができればTeitterAPIを使用したアプリケーションの作成は攻略したも同然なので、
あとはどのようなサービスにするかだけ考えて実装すればいいんじゃないでしょうか!
はまったこととしては
- importに未使用のパッケージを定義するとエラーになる
- 変数などに格納して1度も使用しないとエラーになる
- 読み込んでいるパッケージ群の中で同じメソッド名で定義していた場合はエラーになる
ということでした。。
厳しいと思いつつ、かなり厳密なプログラムが出来上がるのでとてもいいと思います(毎回プログラムが雑すぎるということなので注意しなければならないですね。。)
最後にソースコードをあげておきます。
kaisou4537/revelTwitterApp · GitHub
以上、長々とありがとうございました!