https://github.com/sue445/pribirthdaybot をTwitter API v2移行した時のメモ
tl;dr;
- https://github.com/sferik/twitter はv2対応してないので別のgemに移行する
- v2だとアクセストークンに有効期限がつくようになったのでちょい面倒
移行先のgem
自分が当時調べた範囲だとAPI v2対応しているAPIクライアントのgemは下記の2つしかなかったです。
ちなみに前者のsimple_twitterは最近メンテナになりました。
その他に必要になりそうなgem
TwitterのOAuth2のリフレッシュトークンからアクセストークンを取得するのに必要だったgem
ウェブアプリでTwitterのOAuth2認証したい場合に必要なgem
botでAPI v2対応する時の注意点
アクセストークン(厳密にはベアラートークン)には有効期限がある(約2時間)ので、botで利用する時には実行時にリフレッシュトークンからトークンリフレッシュを行い毎回新しいアクセストークンを生成する必要があるのですが、一度利用したリフレッシュトークンは使えなくなるのでトークンリフレッシュの時に返ってくるリフレッシュトークンをDBとかに保存しておく必要があります。(このリフレッシュトークンを次回実行時に使う)
追記: 2023/07/21 10:40
これ書いた後に知ったんだけどAPI v2を使う上でOAuth2は必須ではない(一部のエンドポイントはOAuth 1.0aのアクセストークンとかでTwitter API v2が使えるらしい *1 )ので、OAuth1.0aであればリフレッシュトークンは考えなくてよさそう
手順
リフレッシュトークンを作成する
一番最初にリフレッシュトークンを取得するところだけは手で作る必要があります。
自分用にはこういうアプリをローカルで動かして認証するようにしていました。
Twitter Appについているデフォルトのトークンでもいいんですが、Appを管理しているTwitterアカウントとbotのTwitterアカウントが異なる場合にはこっちの方がいいと思います。( https://developer.twitter.com/ への登録は電話番号認証が必要なのでなるべく1つのTwitterアカウントに集約させたい)
権限はTwitter botの要件であればこれで十分。 *2
# https://developer.twitter.com/en/docs/authentication/oauth-2-0/authorization-code TWITTER_V2_SCOPE = "tweet.read tweet.write users.read offline.access"
リフレッシュトークンを使う場合には最低限 offline.access
は必須。他は用途に応じて調整してください。
このアプリをローカルで動かせば下記のようなjsonが返ってくるので、ここにあるtokenとrefresh_tokenを使います。
{ "provider": "twitter2", "uid": "14540215", "info": { "name": "sue445", "email": null, "nickname": "sue445", "description": "フルスタックキュアエンジニア。 プリキュア/サザエさん/プリパラ/プリ☆チャン/プリマジ/オヤジギャグコミッタ 【警告】上級者向けアカウント。フォローすると実況ですごい勢いでTLが埋まるよ!【危険】", "image": "https://pbs.twimg.com/profile_images/378800000394619528/fb8a746f6955be08134050ba2adaa1f2_normal.png", "urls": { "Website": "https://t.co/fZVVmoHpLx", "Twitter": "https://twitter.com/sue445" } }, "credentials": { "token": "XXXXXXXXXXXXXXXXXXXXXX", "refresh_token": "XXXXXXXXXXXXXXXXXXXXXX", "expires_at": 1689828440, "expires": true }, "extra": { "raw_info": { "data": { "verified": true, "protected": false, "description": "フルスタックキュアエンジニア。 プリキュア/サザエさん/プリパラ/プリ☆チャン/プリマジ/オヤジギャグコミッタ 【警告】上級者向けアカウント。フォローすると実況ですごい勢いでTLが埋まるよ!【危険】", "entities": { "url": { "urls": [ { "start": 0, "end": 23, "url": "https://t.co/fZVVmoHpLx", "expanded_url": "http://sue445.hatenablog.com/", "display_url": "sue445.hatenablog.com" } ] } }, "name": "sue445", "location": "Tokyo / Japan", "id": "14540215", "profile_image_url": "https://pbs.twimg.com/profile_images/378800000394619528/fb8a746f6955be08134050ba2adaa1f2_normal.png", "url": "https://t.co/fZVVmoHpLx", "created_at": "2008-04-26T05:33:43.000Z", "public_metrics": { "followers_count": 2859, "following_count": 1678, "tweet_count": 456027, "listed_count": 182 }, "username": "sue445" } } } }
botでのAPI v2移行
自分がsimple_twitterのメンテナをしてるってことでsimple_twitterを例に出しますが全体的な流れはtweetkitでもそんなに変わらないと思います。
Gemfile
に下記を追加。
gem "simple_twitter" gem "twitter_oauth2"
こういうclassを追加 *3
# frozen_string_literal: true class TwitterClient API_ENDPOINT = "https://api.twitter.com/2" class Error < StandardError end # @return [Hash] def get_me simple_twitter_client.get("#{API_ENDPOINT}/users/me") end # @param [String] text def post_tweet(text) simple_twitter_client.post("#{API_ENDPOINT}/tweets", json: { text: text }) end private # @return [String] def access_token return @access_token if @access_token oauth2 = TwitterOAuth2::Client.new( identifier: ENV["TWITTER_V2_CLIENT_ID"], secret: ENV["TWITTER_V2_CLIENT_SECRET"], ) # FIXME: refresh_tokenをDBなどから取得する oauth2.refresh_token = load_refresh_token ret = oauth2.access_token! # FIXME: refresh_tokenをDBなどに保存する save_refresh_token(ret.refresh_token) @access_token = ret.access_token end # @return [SimpleTwitter::Client] def simple_twitter_client @simple_twitter_client ||= SimpleTwitter::Client.new(bearer_token: access_token) end end
ここでポイントになるのがrefresh_tokenの読み込みと保存です。
priborthdaybotだと実行環境にCloud Functionsを使っているのでFirestoreに保存するようにしていますが、ここはアプリの要件によって変わると思います。(だいたいはRDBやKVSになるはず)
具体的な作業内容は https://github.com/sue445/pribirthdaybot/pull/61/files を見てください。
*1: https://github.com/PLhery/node-twitter-api-v2/blob/1.15.0/doc/basics.md , https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets
*2: https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets
*3:https://github.com/sue445/pribirthdaybot/blob/15b4507bc4faa12c4d1722f0b2470cb55e5893d6/lib/twitter_client.rb