Closed14

Twitter API V2 (javascript)

hidetaka okamotohidetaka okamoto

コード以外の部分で感じたことメモ

  • Twitter Devアカウントの登録画面がBad UI (freeプラン申込ボタンが隠されている)
  • 電話番号認証を対象アカウントでやった方が良いかも?
hidetaka okamotohidetaka okamoto

認証系

  const { Client, auth } = require( "twitter-api-sdk");
  const {randomBytes} = require("crypto");
    const challenge = randomBytes(12).toString('hex');
    const authClient = new auth.OAuth2User({
        client_id: oauth.clientId,
        client_secret: oauth.clientSecret,
        callback: "http://127.0.0.1:3000/callback",
        scopes: ["tweet.write", "offline.access"],
      });
    const authUrl = authClient.generateAuthURL({
      state: "test",
      code_challenge: challenge
      code_challenge_method: 'plain'
  });
hidetaka okamotohidetaka okamoto

これでtokenとれた。

    const authClient = new auth.OAuth2User({
        client_id: oauth.clientId,
        client_secret: oauth.clientSecret,
        callback: "http://127.0.0.1:3000/callback",
        scopes: ["tweet.write", "offline.access"],
      });
  const authUrl = authClient.generateAuthURL({
    state: "test",
    code_challenge: challenge
    code_challenge_method: 'plain'
});
authClient.requestAccessToken(CODE)
.then(console.log)
.catch(console.log)

generateAuthURLを飛ばすと、error_description: 'Missing required parameter [code_verifier].'が飛んでくるのは、ちょっとよくわかってない

hidetaka okamotohidetaka okamoto

Scopeミスってた。

      const authClient = new auth.OAuth2User({
          client_id: oauth.clientId,
          client_secret: oauth.clientSecret,
          callback: "http://127.0.0.1:3000/callback",
-          scopes: ["tweet.write", "offline.access"],
+          scopes: ["tweet.write", "offline.access", "tweet.read", "users.read"],
        });
hidetaka okamotohidetaka okamoto

いけた

      const authClient = new auth.OAuth2User({
          client_id: oauth.clientId,
          client_secret: oauth.clientSecret,
          callback: "http://127.0.0.1:3000/callback",
          scopes: ["tweet.write", "offline.access", "tweet.read", "users.read"],
          token: token
        });
    const client = new Client(authClient);
    client.tweets.createTweet({
        text: "hello twitter api!"
    }).then(console.log).catch(console.log)
hidetaka okamotohidetaka okamoto

Refresh Tokenを使ったトークンの更新


      const authClient = new auth.OAuth2User({
          client_id: oauth.clientId,
          client_secret: oauth.clientSecret,
          callback: "http://127.0.0.1:3000/callback",
          scopes: ["tweet.write", "offline.access", "tweet.read", "users.read"],
          token: token
        });
    const newToken = await authClient.refreshAccessToken()
    console.log(newToken)

    const authClient2 = new auth.OAuth2User({
        client_id: oauth.clientId,
        client_secret: oauth.clientSecret,
        callback: "http://127.0.0.1:3000/callback",
        scopes: ["tweet.write", "offline.access", "tweet.read", "users.read"],
        token: newToken.token
      });
    const client = new Client(authClient2);
    client.tweets.createTweet({
        text: "try to use the resfresh token"
    }).then(console.log).catch(console.log)

hidetaka okamotohidetaka okamoto

expires_atにunixtimestampが入ってるので、これを見て更新処理を入れる感じかな。

hidetaka okamotohidetaka okamoto

Next step

  • CDKかServerless Frameworkあたりでbotアプリにする
  • キーの管理はSSMのParameter Store(暗号化)ですませておく
  • Cloudflare Workersにまとめて突っ込まれてるバッチ系の一部を移す
hidetaka okamotohidetaka okamoto

だいたいこんな感じになった。

    const authClient = new auth.OAuth2User({
        client_id: oauth.clientId,
        client_secret: oauth.clientSecret,
        callback: "http://127.0.0.1:3000/callback",
        scopes: ["tweet.write", "offline.access", "tweet.read", "users.read"],
        token: token
    });
    const diffFromTheExpiresAt = new Date(token.expires_at).getTime() - new Date().getTime()
    if (diffFromTheExpiresAt < 0) {
        console.log("You should refresh its token")
        const newToken = await authClient.refreshAccessToken()
        console.log(newToken)
    }
    const authClient2 = new auth.OAuth2User({
        client_id: oauth.clientId,
        client_secret: oauth.clientSecret,
        callback: "http://127.0.0.1:3000/callback",
        scopes: ["tweet.write", "offline.access", "tweet.read", "users.read"],
        token: newToken.token
    });
    const client = new Client(authClient2);
    client.tweets.createTweet({
        text: "try to use the resfresh token at:" + new Date().toDateString()
    }).then(console.log).catch(console.log)
このスクラップは2023/06/12にクローズされました