前回Twitter APIを用いてツイート取得やアカウントの取得について書いた。
今回はツイート編。
目次
長くなるので目次
Twitter API V2を用いてツイートをする
最近Twitter APIのv2を用いたツイートについて試していたがこれが結構個人的にはハマってしまい、ようやくプログラムから自動でツイートできるようになったというところ。
Twitter APIを用いてツイートした際の表示
本題に入る前に...
Twitter APIに関する開発者の間では常識かもしれないが、一応メモとしてTwitter API経由で呟いた場合、アプリ作成時に設定した名前がツイート上には表示される。
上が実際にツイートしたところのキャプチャであり、下記がTwitter API側のダッシュボードのアプリ名のキャプチャ。
ここに設定した名前がツイートの際には記載される。
Twitter API v2を用いてツイートをするまでに参考にしたところ。
下記のSDKを用いたが、こちらのexampleとして記載されているこのコードを大いに参考している。
他にも参考にできそうなところがあれば参考にしたいところだったが、参考になりそうなものを見つけることができなかった。
Twitter API V2はPostmanやGlitchアプリなどでのサンプルは用意されているのだが、コードレベルで認証部分も含めたコードというのが私が知る限りではなく、そういった意味でも少々苦労した。
コピペで貼ればTwitter API V2を用いてツイートできるコードがどこかにあればいいのに...もしご存じの方はコメントいただけると幸いです。
Twitter API V2を用いてツイートするサンプルコード
サンプルコードを実装する前に認証設定について紹介しておく。
Twitter APIの認証設定
Twitter APIのdashboardから利用するアプリの User authentication settings
を開き、下記のような設定にしておく必要がある。
OAuth 2.0を有効にしておく
Type of App
は Automated App or Bot
にした。
(これはテストとして選択しているに過ぎないので、本来であれば利用用途にあったTypeを選択することになる)
なお選択するタイプによって必要となる認証方法が異なってくる
(詳細は公式ドキュメントを参照)
例えば下記のようにSingle page appを選択している場合、認証時に client_secret
は不要となる。
※下記はあとに貼るコードとなるが、この場合は実行するコードは下記のような形となる。
const authClient = new auth.OAuth2User({ client_id: process.env.CLIENT_ID, // client_secret: process.env.CLIENT_SECRET, // ここが不要になる callback: "http://127.0.0.1:3000/callback", scopes: ["tweet.read", "tweet.write", "users.read", "offline.access"], });
詳細な認証については必ず公式ドキュメントを参照し、適した認証方式を採用するように気をつける必要がある。
また、今回記載したコードはいろいろ試しながら書いたコードなので、必ずしも最低限の権限とはなっていない点に注意。
scopesとして指定されている offline.access
も、このあと貼るコードのように一度の認証のみで済む内容であれば本来付ける必要はない。
上にも書いたが、ここについては実際に開発していく際は公式ドキュメントを参照した上で実装を進めていくのが良い。
Callback URLは http://127.0.0.1:3000/callback
としている。
ちなみにWebsite URLはなんでもいいようなので、特に貼りたいサイトがなければ自分のTwitterのプロフィールページのURLとかでもOKそう。
サンプルコード
ここからは実装に移る。
今回もTypeScriptのSDKを用いている。
またOAuth2 認証の関係でExpressを用いている。
本当はCLIツールという体裁でツイートできるものを作りたかったが、ひとまずは愚直にサーバ上で諸々処理を行っていくスタイルで。
(というか、上のexampleを大いに参考にしているだけですが)
追記:CLI上でツイートまで完結できる(OAuth2の認証のみブラウザ)プログラムを書いたので貼っておく
まずは依存関係のインストール。
yarn add twitter-api-sdk express
次にコード。
ちなみにESMで書いています。(.mjs
)
STATE
など諸々の記述はサンプル用であることに注意。
import { Client, auth } from "twitter-api-sdk"; import express from "express"; const authClient = new auth.OAuth2User({ client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, callback: "http://127.0.0.1:3000/callback", scopes: ["tweet.read", "tweet.write", "users.read", "offline.access"], }); const app = express(); const client = new Client(authClient); const STATE = "my-state"; app.get("/login", async function (req, res) { const authUrl = authClient.generateAuthURL({ state: STATE, code_challenge_method: "s256", }); res.redirect(authUrl); }); app.get("/callback", async function (req, res) { try { const { code, state } = req.query; if (state !== STATE) return res.status(500).send("State isn't matching"); await authClient.requestAccessToken(code); res.redirect("/post_tweet"); } catch (error) { console.log(error); } }); app.get('/post_tweet', async function (req, res) { try { const postTweet = await client.tweets.createTweet({ // 呟く内容をここに記載 text: "#TwitterAPI からのテスト投稿" }); res.send(postTweet); } catch (error) { console.log('=== Tweet error ==='); console.log(error); }; }) app.listen(3000, () => { console.log(`Go here to login: http://127.0.0.1:3000/login`); });
これを tweet.mjs
とかで保存して、あとは下記のように実行する。
CLIENT_ID=<取得したCLIENT ID> CLIENT_SECRET=<取得したCLIENT SECRET> node tweet.mjs
ツイッターにログインした状態で http://127.0.0.1:3000/login
にアクセスすると下記のような画面になるので、アプリにアクセスを許可
を選択する。
(ログインしていなければ、ここでログインを促される)
認証が問題なければ client.tweets.createTweet
が呼ばれてツイートされるといった具合です。
APIを触ってみた上でのメモ
scopesのタイポで時間が溶けた
最初 scopes
内でタイポしていた。
const authClient = new auth.OAuth2User({ client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, callback: "http://127.0.0.1:3000/callback", scopes: ["tweet.read", "tweet.write", "user.read", "offline.access"], // 本当はusers.read });
この状態でアプリを起動してログインしようとすると、下記のような画面になる。
最初別のところに原因があるのかと思い、Appの認証設定とかを見直しまくっていたが、ただのタイポだったというオチ。これで割と時間が溶けた。
というか、今振り返ればこれの調査で大半の時間を使っていたかも...
必要なscopesの調べ方
API V2ではscopes
内で利用したい権限を記載する。
当然ツイートを取得するだけの場合と、自分でツイートする場合では必要となるscopesも異なってくる。
ツイートをする際に必要になるscopesについては公式ドキュメントに記載されている。
POST /2/tweets | Docs | Twitter Developer Platform
上を見ると、ツイートを行うためには下記の3つのscopesが必要になることがわかる。
今回はこれらに加えて、offline.access
も追加している形。
(でも今回の処理であればいらなかったかも)
scopesとログイン時の権限許可に関する文言について
scopesに応じて、ログイン時に許可を促される権限の文言が変わる。例えば上のようにscopesを、
と設定した場合、下記のようにログイン画面には表示される。
もし tweet.write
と offline.access
のみにすると、
となる。
Twitter API上から同一文言のツイートはできない?
テストで同一内容のツイートを行ってみようとしたところエラーになった。
error: { detail: 'You are not allowed to create a Tweet with duplicate content.', type: 'about:blank', title: 'Forbidden', status: 403 }
ツイート自体は重複でもできると思うし、重複したツイートは許可されていないと書かれているのでAPI側の設定次第でどうにかなるのかもしれない。
今回は以上となります。