🛞

Twitter API のバージョンを 1.1 から 2 へ動作確認しつつ移行し、Rubyプログラムからツイートする

2023/04/13に公開

Twitter API のプランが整備され、Standard(v1.1)APIを利用している場合は正式にv2へ移行するよう勧告がありました。

https://twitter.com/TwitterDev/status/1641222782594990080?s=20

もともとv1.1を利用していたアプリで、移行するときにやや苦労したため、記録を残します。

状況整理

移行前は、次のような状況でした。

  • Twitter API v1.1を利用している
  • Developer Portal では スタンドアロンアプリ(Standalone Apps)として表示されている
  • このAPIv1.1を Ruby の twitter gem で利用していた
  • API を使ってやっていたこととしてはツイートの投稿のみ

Twitter API v2 でRubyプログラムからツイート投稿できるようにしたいです。

やったことのまとめ

先に流れをまとめます。以下の作業を行いました。

  • ツイート投稿確認用アカウントの作成
  • Postmanでv2 APIを使い投稿してみる
  • 運用アカウントでv2を使えるようにする
  • Rubyプログラムを修正する

ひとつずつ見ていきます。

確認用アカウントの作成

Twitter API v2は、(v1.1もですが)いわゆるDry-runができず、正しくツイートされることを確認するには、実際にツイートを投稿するしかなさそうでした。いきなり運用中のアカウントでツイートを投稿しても良いのですが、多くの人に見られているアカウントの場合、ためすのに気を遣います。

そこで、個人のアカウントでDeveloper Portalをオープンし、そのアカウントでv2でのツイートを試すことにしました。Developer Portalの開始はこちらから行えます。私がつくったときは、電話番号の登録が必要でした。

https://developer.twitter.com/ja/docs/basics/developer-portal/overview

プロジェクトを作成

ダッシュボードから作成できます。

プロジェクトに紐づくアプリを作成

プロジェクトを作成するとその流れでアプリも作成できるので、ウィザードにしたがってアプリをつくります。以下のような状態になりました。

Access Token and Secret を作成(OAuth1.0a認証のため)

アプリの画面で、Keys and tokensタブ > Authentication TokensAccess Token and Secret を生成します。OAuth1.0a認証でツイート投稿するために利用します。このあたり最初理解が追いつかずに時間をとってしまったのですが、トークンの種類とできることとしては以下のような関係になっていると認識しています。

Consumer Keys

こちらのキーとシークレットは、Twitterアプリの開発者であることを認証するためのものです。参考

Access Token and Secret

いま生成したアクセストークンとシークレットは、OAuth 1.0a APIリクエストを認証するために使用されるユーザー固有の認証情報です。リクエストを代行するTwitterアカウントを指定します。結論としてはこれらのAPIキー・シークレットとアクセストークン、シークレットでツイートします。参考

Bearer Token

Authentication Token のところ、もうひとつ生成できますね。Bearer Tokenです。これはドキュメントを読む限り「アプリケーション単独認証」を行うときに利用するもので、タイムラインの取得やツイート検索が行えるとありました。参考

ところが、ここにプランの話が絡んできます。ソースが見つけられませんでしたが、無料プランで呼べるAPIはおそらく以下です。

  • POST https://api.twitter.com/2/tweets ツイート投稿
  • DELETE https://api.twitter.com/2/tweets/:id ツイート削除
  • GET https://api.twitter.com/2/users/me 認証ユーザーの情報を取得

つまりツイートの検索はできません。無料のアプリケーション単独認証ではほとんど何もできない説が浮上しています。[要出典]

User authentication settings

ここはいわゆる「ツイッターでログイン」を実装して、ログインユーザーに代わってアプリがなにかする、という機能を実装するときに使うものです。動作確認では不要、と思いきや、設定する必要があります。さきほど生成したAccess Token and Secretは、デフォルトでは Read only 権限で、ツイート投稿ができません。この権限を変更し、ツイート投稿可能とするには利用予定のない User authentication settings を有効にしなければなりません。なんじゃそりゃ...

コールバックURLは使わないので適当でいいです。一番上のアプリの権限だけ Read and write に変えておきましょう。この導線について他のユーザーがどう感じているか気になる方はこちらのフォーラムも覗いてみてください。

https://twittercommunity.com/t/changing-app-permissions-missing-in-ui/163708

ここまでのまとめ

いろいろ書きましたが、Freeプランでツイート投稿するために、Twitter Developer Portal で以下のことを行いました:

  1. プロジェクトを作成
  2. プロジェクトに紐づくアプリを作成
  3. Consumer Keys(API Key and Secret)と Access Token and Secret を OAuth1.0a認証で使うため発行する
  4. Access Token を発行しただけでは Read only 権限であるため、User authentication settings を有効としてアプリ権限を Read and write にする

これでトークンの準備ができました。この手順は新しくTwitter APIの利用を開始するときも利用できるはずです。

Postman で動作確認

発行した各種キーでツイート投稿できることを確認したいです。まずは Twitter API v2 の Postman プロジェクトがあるので、それをforkまたはimportしましょう。

https://developer.twitter.com/ja/docs/tutorials/postman-getting-started

ご自身のアカウントで Twitter API v2 のCollectionsが見えるようになればOKです。

各種キーを設定

左ペインで Environments を選びます。おそらく空だと思うのでTwitter API v2など名前をつけて環境変数を作成します。consumer_key,consumer_secret,access_token,token_secretを埋めます。

  • consumer_key: API Key
  • consumer_secret: API key secret
  • access_token: Access token
  • token_secret: Access token secret

それぞれこのように対応します。詳細は認証ページの用語の説明を参照してください。

https://developer.twitter.com/ja/docs/authentication/oauth-1-0a/obtaining-user-access-tokens

ユーザー情報の取得を実行する

ここまでできたらあとはAPIを叩きます。失敗しても問題ない取得系から。CollectionsからUser Lookup>Authenticated User Lookupとしてください。

  1. Environmentsを有効にできます。さきほど用意した Twitter API v2 を指定してください
  2. 私がimportした時点では、ここのリクエスト先がhttps://api.twitter.com/2/meになっていました。間違っているのでhttps://api.twitter.com/2/users/meに直します
  3. 取得するフィールドをここで指定します。動作確認なのでnameのみ指定します

Authを設定する

次にAuthタブで認証を設定します。

  1. 認証方法はOAuth1.0です
  2. 認証トークンはリクエストヘッダに入れます
  3. ここで値を直入れするのではなく、環境変数で設定したパラメータを参照するようにします

リクエストを送ってください。レスポンスがゲットできれば成功です!少なくともAPIキーが正しく利用できていることが確認できました。

ツイート投稿してみる

同じ要領でツイートできます。Collectionsから Manage Tweets > Create a Tweet とします。認証設定はユーザー情報取得のときと同じです。書き込み権限も追加しているので、ツイートに成功するはずです。

これでOAuth1.0aによる認証と、それを利用したツイート投稿が成功すると確認できました。次のステップへ行きます。

運用アカウントでv2を使えるように

ここまでは確認用のアカウントでしたので、運用アカウントのDeveloper Portalで作業します。Standalone App として利用しているアプリを、プロジェクトに紐付けることとなります。プロジェクトを作成すれば紐付けるナビゲーションが出てきますので手順に従います。Standalone Appの表記がなくなればOKです。

なお、もともとツイート投稿をしていた場合、Access Token and Secretの権限は Read and Write になっているはずなので、この場合はUser authentication settings不要です。

運用アカウントのv2対応はこれでOKです。

Rubyプログラムの修正

Postmanでのリクエストと同じことをRubyのプログラムに落とし込むのですが、もともと利用していた twitter gem は v1.1 しかサポートしていません。公式ドキュメントには tweetkitが紹介されているのですが...

https://developer.twitter.com/en/docs/twitter-api/tools-and-libraries/v2

コードの更新が2年前と、若干メンテナンス状態に不安があります。結局、httpsimple_oauthを使って実装することにしました。simple_oauthもどうなんだという話ももちろんあると思います。軽量でOAuth1.0のシグネチャを生成できるgemがあれば乗り換えたいです。

tweet.rb
class Tweet
  require "http"
  require "simple_oauth"
  POST_TWEET_ENDPOINT = "https://api.twitter.com/2/tweets".freeze

  HEADERS = {
    "Content-Type": "application/json",
    "User-Agent": "My-Tweet-Bot"
  }.freeze

  def send_tweet(text)
    # credentials は Rails シークレットや環境変数から読み出すHashです。ご自身の環境に合わせて修正してください。
    client = HTTP.auth(auth_header("POST", POST_TWEET_ENDPOINT, {
      consumer_key: credentials[:twitter_consumer_key],
      consumer_secret: credentials[:twitter_consumer_secret],
      token: credentials[:twitter_access_token],
      token_secret: credentials[:twitter_access_token_secret],
    }))
    client.post(POST_TWEET_ENDPOINT, headers: HEADERS, json: { text: })
  end

  # OAuth1.0aで Authentication ヘッダのシグネチャを生成します。これにSimpleOAuthを利用
  def auth_header(method, url, auth_params)
    SimpleOAuth::Header.new(method, url, {}, auth_params).to_s
  end
end

参考にしたコード:

このコードを利用して、ツイートが投稿できればv2への移行は成功です。不安な場合は各種APIキーの値を確認用アカウントに置き換えてから試しにツイートすると良いです。

まとめ

v1.1からv2への移行そのものはDeveloper Portalで作業すればすぐ終わるのですが、つまづくポイントがたくさんありました:

  • OAuth1.0aとOAuth2.0でできることに違いがあるのに気づくのが遅れた


https://developer.twitter.com/ja/docs/authentication/overview

  • Freeプランと各種トークンの組み合わせで、できることがかなり限定的になる点がわかりにくい
  • 新しくアプリを作る場合、ツイート投稿の権限を付与するためにTwitter認証の設定が必要になる(わざとわかりにくくしているのかと疑ってしまいます)
  • Rubyにおいて、gemのTwitter API v2対応がまちまち、どこまで自分で実装するか迷った

間違いやかわっている点があれば教えてください

ドキュメントを転々としつつまとめたので、とくに認証周りの記述で間違っている点があればコメントをもらえると嬉しいです。また、このあたりTwitter側も動きが激しそうなので、Outdatedな点を見つけたらそちらも教えていただけると助かります。

少しでもみなさまのv2移行のお役に立てれば幸いです。

追記: 移行後、Twitter API がサスペンド(凍結)されてしまった場合

とくに使い方を変えていないのですが、API v2 へ移行してしばらく利用していると突然ツイートできなくなってしまいました。それで、Developer Portal へアクセスすると当該アプリで以下のような表示が。

SUSPENDED This App has violated Twitter Rules and policies. As a result, it can no longer be accessed. For assistance, submit a support ticket.

さっそくサポートチケットを発行するべくリンクを踏みますが…該当するページは存在しないらしく、サポートページのトップへリダイレクトされます。がぎぐげごご(いろいろ言いたいことがあるがこらえている音)

結論として、この記事に助けられました。

https://qiita.com/uehatsu/items/7d13485c00d95e76da7e

アプリをひとつだけにして、Productsへ遷移、ページの中央にある Downgrade を押してください。そうすると警告は消えるはずです。

再度 Standalone Apps に戻る可能性がある

これで解消したかと思いきや、まだツイートに失敗します。どうやら、アプリが Standalone App に戻ってしまったようです。同じ手順でプロジェクトに紐付けられるので、やり直してください。ここまでやると、再度ツイートが成功するようになりました。

Discussion