https://github.com/sue445/pribirthdaybot をTwitter API v2移行した時のメモ
tl;dr;
移行先のgem
自分が当時調べた範囲だとAPI v2対応しているAPIクライアントのgemは下記の2つしかなかったです。
github.com
github.com
ちなみに前者のsimple_twitterは最近メンテナになりました。
sue445.hatenablog.com
その他に必要になりそうなgem
TwitterのOAuth2のリフレッシュトークンからアクセストークンを取得するのに必要だったgem
github.com
ウェブアプリでTwitterのOAuth2認証したい場合に必要なgem
github.com
botでAPI v2対応する時の注意点
アクセストークン(厳密にはベアラートークン)には有効期限がある(約2時間)ので、botで利用する時には実行時にリフレッシュトークンからトークンリフレッシュを行い毎回新しいアクセストークンを生成する必要があるのですが、一度利用したリフレッシュトークンは使えなくなるのでトークンリフレッシュの時に返ってくるリフレッシュトークンをDBとかに保存しておく必要があります。(このリフレッシュトークンを次回実行時に使う)
追記: 2023/07/21 10:40
これ書いた後に知ったんだけどAPI v2を使う上でOAuth2は必須ではない(一部のエンドポイントはOAuth 1.0aのアクセストークンとかでTwitter API v2が使えるらしい *1 )ので、OAuth1.0aであればリフレッシュトークンは考えなくてよさそう
手順
リフレッシュトークンを作成する
一番最初にリフレッシュトークンを取得するところだけは手で作る必要があります。
自分用にはこういうアプリをローカルで動かして認証するようにしていました。
github.com
Twitter Appについているデフォルトのトークンでもいいんですが、Appを管理しているTwitterアカウントとbotのTwitterアカウントが異なる場合にはこっちの方がいいと思います。( https://developer.twitter.com/ への登録は電話番号認証が必要なのでなるべく1つのTwitterアカウントに集約させたい)
権限はTwitter botの要件であればこれで十分。 *2
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"
}
}
}
}
自分がsimple_twitterのメンテナをしてるってことでsimple_twitterを例に出しますが全体的な流れはtweetkitでもそんなに変わらないと思います。
Gemfile
に下記を追加。
gem "simple_twitter"
gem "twitter_oauth2"
こういうclassを追加 *3
class TwitterClient
API_ENDPOINT = "https://api.twitter.com/2"
class Error < StandardError
end
def get_me
simple_twitter_client.get("#{API_ENDPOINT}/users/me")
end
def post_tweet(text)
simple_twitter_client.post("#{API_ENDPOINT}/tweets", json: { text: text })
end
private
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
oauth2.refresh_token = load_refresh_token
ret = oauth2.access_token!
FIXME
save_refresh_token(ret.refresh_token)
@access_token = ret.access_token
end
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 を見てください。