2017/09/10
バズるものを作れる瞬発力を身に付けたくてTwitterのOAuth認証使ってツイートできるやつを作れるようになっておきたかった。アイデアはまだ無い。 GoのWebアプリケーションフレームワーク Ginを使ってTwitter OAuthでトークン取得するところまで試してみた。
さくっと書きたいからsinatra likeなやつを探した。 その中で現時点でGitHub Starが一番多そうなGinを選んだ。
前回のgo-twitterを使ってみた記事に引き続きCloud9( http://c9.io )さんを使いました。そろそろ有料プランも検討せねば。
http://92thunder.hatenablog.com/entry/2017/09/04/031706
前回は大丈夫だったがgo getでエラーが発生したのでこちらを参考に解決した。 http://qiita.com/syossan27/items/ad05e5060d2ac0fd7adc
main.go Ginって標準でsession使えないのか…って思いつつ追加した。
https://github.com/gin-gonic/contrib/tree/master/sessions
package main import ( "flag" "log" "net/http" "os" "github.com/coreos/pkg/flagutil" gt "github.com/dghubble/go-twitter/twitter" "github.com/dghubble/oauth1" "github.com/dghubble/oauth1/twitter" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" ) func main() { // 環境変数からconsumer-key, consumer-secretを取得 flags := flag.NewFlagSet("app-auth", flag.ExitOnError) consumerKey := flags.String("consumer-key", "", "Twitter Consumer Key") consumerSecret := flags.String("consumer-secret", "", "Twitter Consumer Secret") flags.Parse(os.Args[1:]) flagutil.SetFlagsFromEnv(flags, "TWITTER") if *consumerKey == "" || *consumerSecret == "" { log.Fatal("Consumer key/secret required") } config := oauth1.Config{ ConsumerKey: *consumerKey, ConsumerSecret: *consumerSecret, Endpoint: twitter.AuthorizeEndpoint, } // ginのrouter初期化 router := gin.Default() store := sessions.NewCookieStore([]byte("secret")) // セッションの設定 router.Use(sessions.Sessions("oauth-tweet-test-session", store)) // templatesディレクトリを登録 router.LoadHTMLGlob("templates/*") // GET / // アクセストークンがセッションに入っていれば表示 // 入ってなければrequestTokenを取得してOAuth認証ページにリダイレクト router.GET("/", func(c *gin.Context) { session := sessions.Default(c) accessToken := session.Get("access_token") accessSecret := session.Get("access_secret") if accessToken == nil || accessSecret == nil { requestToken, requestSecret, _ := config.RequestToken() session.Set("request_secret", requestSecret) session.Save() c.Redirect(http.StatusFound, "https://api.twitter.com/oauth/authenticate?oauth_token="+requestToken) } else { c.HTML(http.StatusOK, "index.tmpl", gin.H{ "test": "hello world", }) } }) // GET /callback // OAuth認証ページからこのアプリを許可したらリダイレクトされてくる // このあたりはTwitter Application Managementで設定 // URLに入っているoauth_token, oauth_verifierと // GET /で取得していたrequestSecretを使ってアクセストークン取得 router.GET("/callback", func(c *gin.Context) { oauthToken := c.Query("oauth_token") oauthVerifier := c.Query("oauth_verifier") session := sessions.Default(c) requestSecret := session.Get("request_secret").(string) accessToken, accessSecret, _ := config.AccessToken(oauthToken, requestSecret, oauthVerifier) session.Set("access_token", accessToken) session.Set("access_secret", accessSecret) session.Save() c.Redirect(http.StatusFound, "/") }) // POST /post // access token/secret を使ってツイート投稿する router.POST("/post", func(c *gin.Context) { session := sessions.Default(c) accessToken := session.Get("access_token") accessSecret := session.Get("access_secret") if accessToken == nil || accessSecret == nil { log.Fatal("Invalid access token/secret.") } config := oauth1.NewConfig(*consumerKey, *consumerSecret) token := oauth1.NewToken(accessToken.(string), accessSecret.(string)) httpClient := config.Client(oauth1.NoContext, token) client := gt.NewClient(httpClient) client.Statuses.Update("oauth test", nil) c.Redirect(http.StatusFound, "/") }) router.Run() }
templates/index.tmpl
<html> <head> </head> <body> <h3>OAuth Tweet Test</h3> <form method="post" action="/post"> <button type="submit">Post</button> </form> </body> </html>
export TWITTER_CONSUMER_KEY=xxx export TWITTER_CONSUMER_SECRET=xxx go get . go run main.go
認証ページにリダイレクトされてツイートするとこまでできた。