(2023/05/16) コメントにて、「GASからの初回認証時に『ReferenceError: OAuth2 is not defined』エラーになる」というご指摘をいただきました。こちら、GAS側でライブラリを追加していないと発生するエラーです。ライブラリ追加に関する記載が抜けていたので追加しました。ご指摘ありがとうございました。
本記事では、Google Apps Script(GAS)からTwitterのAPI経由でツイッターに投稿する方法を紹介します。

↑のツイッターアカウントでは、ブログの更新をした際に手動でURLを貼り付けてお知らせをしているのですが、どうしても忘れてしまいます。そこで、ブログ更新のお知らせを自動で投稿できるようにしたいと考えました。とはいえ、最初から色々と機能を盛り込むのも大変なので、まずはAPI経由でツイートするところまでを作成します。
Twitter APIは、3/29に新しいAPIが発表になりましたが、本記事は新しいAPI(Twitter API v2)のFreeプランで動かしています。新しいTwitter APIに関する詳細は以下をご参照ください。
Twitter側の設定
Twitter APIの登録
まず、Twitter Developer Platformを開き、ご自身のTwitterアカウントでログインします。
Twitterアプリケーションの作成
ログインすると以下の画面が開きますので、右上の「Create an App」を押します。

「Apply」を押します。

「Ready to build on Twitter?」という画面が開きます。

(まだの場合のみ)電話番号認証
Twitter APIの利用には電話番号認証が必要となりますので、まだの方は「Verify Phone」を押下して電話番号認証を完了させてください。
電話番号は、最初の0を取った番号を入力します。「080-1111-2222」なら「8011112222」となります。

「Next」を押すと、入力した電話番号にショートメールで認証コードが届きますので、次のページで入力してください。入力後、自分のツイッターの画面に遷移すれば認証完了です。
完了したら、ページを更新(F5キーまたは、ブラウザの左上の更新アイコンを押下)します。すると、先ほど非活性だったボタンが押せるようになっているはずです。
無料/有料プランを選択

画面の一番下にある「Sign up for Free Account」を押下します。有料プランを登録する場合には「Subscribe」から登録します。
利用目的を記載して利用開始
「Developer agreement & policy」という画面では、Twitter APIの利用目的を記載します。250文字以上入力する必要がありますが、審査されるわけではないので内容はなんでもOKです。

「Submit」を押下すると、開発者ポータル(Developer Poetal)が開きます。

Client ID・Client Secretの取得
左側メニューから、Default project-XXXの下にある、TwitterIDから始まる項目を押下します。

上部のタブから「Keys and tokens」を選択します。

「OAuth 2.0 Client ID and Client Secret」の「Client ID」と「Client Secret」をメモしておきます。(あとでGASのスクリプトに記載します)
Twitter APIの設定
上部のタブから「Settings」を選択します。
「User authentication settings」の「Edit」を押下します。

App permissions
App permissions(required)は「Read and write」を選択します。

Type of App
「Type of App(required)」は「Web App, Automated App or Bot」を選択します。

App info
「App info」は「Callback URI / Redirect URL (required) 」にGASのコールバックURLを設定します。こちらは次章(すぐ下)で詳しく解説しています。
「Website URL (required)」については、そのURLが実在するかどうかまではチェックしていないようなので(参考)、今回は自分のツイッターURLを設定しておきました。

Google Apps Scriptのプロジェクトを作成
Google Apps Script(GAS)を開いて、新しいプロジェクトを作成します。

ここで、コールバックURLを取得しておきます。新規作成したGASのプロジェクトのURLのID部分をコピーして、以下のようにURLを生成します。
https://script.google.com/home/projects/[ここをコピー]/edit
↓
https://script.google.com/macros/d/[コピーしたやつを貼り付け]/usercallback
こちらのコールバックURLを、Twitter APIのApp info>Callback URI / Redirect URL (required) に記載してください。
OAuth2ライブラリの追加
左側メニューから「ライブラリ」を押します。

「スクリプトID」を入力します。

1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF
こちらをコピーしてそのまま貼り付けて「検索」を押し、OAuth2が出てきたら「追加」を押します。

Twitter API認証処理
GASのエディタを開くとデフォルトで作成されている「myFunction」は全て削除し、Twiter APIの認証処理を記載します。
参考:https://twittercommunity.com/t/cannot-auth-my-google-script-app/177367
https://github.com/googleworkspace/apps-script-oauth2
const CLIENT_ID = 'XXX'
const CLIENT_SECRET = 'XXX'
function getService() {
pkceChallengeVerifier();
const userProps = PropertiesService.getUserProperties();
const scriptProps = PropertiesService.getScriptProperties();
return OAuth2.createService('twitter')
.setAuthorizationBaseUrl('https://twitter.com/i/oauth2/authorize')
.setTokenUrl('https://api.twitter.com/2/oauth2/token?code_verifier=' + userProps.getProperty("code_verifier"))
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setCallbackFunction('authCallback')
.setPropertyStore(userProps)
.setScope('users.read tweet.read tweet.write offline.access')
.setParam('response_type', 'code')
.setParam('code_challenge_method', 'S256')
.setParam('code_challenge', userProps.getProperty("code_challenge"))
.setTokenHeaders({
'Authorization': 'Basic ' + Utilities.base64Encode(CLIENT_ID + ':' + CLIENT_SECRET),
'Content-Type': 'application/x-www-form-urlencoded'
})
}
function authCallback(request) {
const service = getService();
const authorized = service.handleCallback(request);
if (authorized) {
return HtmlService.createHtmlOutput('Success!');
} else {
return HtmlService.createHtmlOutput('Denied.');
}
}
function pkceChallengeVerifier() {
var userProps = PropertiesService.getUserProperties();
if (!userProps.getProperty("code_verifier")) {
var verifier = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
for (var i = 0; i < 128; i++) {
verifier += possible.charAt(Math.floor(Math.random() * possible.length));
}
var sha256Hash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, verifier)
var challenge = Utilities.base64Encode(sha256Hash)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '')
userProps.setProperty("code_verifier", verifier)
userProps.setProperty("code_challenge", challenge)
}
}
function logRedirectUri() {
var service = getService();
Logger.log(service.getRedirectUri());
}
CLIENT_ID、CLIENT_SECRET には、Twitter APIの「Client ID・Client Secretの取得」の部分で説明したとおり、「OAuth 2.0 Client ID and Client Secret」の「Client ID」と「Client Secret」を記載してください。
初回実行時は認証が必要
Twitter APIで初回実行する際には、認証が必要です。以下のコードを先ほどのスクリプトに追加します。
参照:https://qiita.com/yuzinet/items/ae4b9ca2b5cd989de435
function main() {
const service = getService();
if (service.hasAccess()) {
Logger.log("Already authorized");
} else {
const authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s', authorizationUrl);
}
}
実行する関数が「main」になっていることを確認して、「実行」を押します。

「承認が必要です」というダイアログが出ますので、「権限を承認」を押します。

「アプリにアクセスを許可」を押します。

「Success!」と表示されたら認証完了です。

承認に成功したら、上記の画面は閉じてしまってOKです。
ツイート処理の実装
ツイート部分の処理を追加します。
参考:https://twittercommunity.com/t/cannot-auth-my-google-script-app/177367
https://qiita.com/yuzinet/items/ae4b9ca2b5cd989de435
function sendTweet() {
var payload = {
text: 'Test tweet from API!!!!!'
}
var service = getService();
if (service.hasAccess()) {
var url = `https://api.twitter.com/2/tweets`;
var response = UrlFetchApp.fetch(url, {
method: 'POST',
'contentType': 'application/json',
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
},
muteHttpExceptions: true,
payload: JSON.stringify(payload)
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
} else {
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s',authorizationUrl);
}
}
実行する関数が「sendTweet」になっていることを確認して、「実行」を押します。実行結果にはツイートID、ツイートしたテキストが出力されます。

ツイッターを確認すると、設定した内容でツイートされていることを確認できました。

注意点
API経由でツイッター投稿をする際の注意点は以下になります。
過去のツイート内容と同じものはツイートできない
Twitter API経由で、過去にツイートした内容と一言一句同じ内容はツイートできません。

対策としては、過去の投稿を削除するか、ツイート内容を一部分でも変更する必要があります。同じような内容を定期的にツイートしたい場合には、日付や管理番号などを付加すると良いかと思います。
無料版の投稿上限は1500回/月まで
Twitter社は3/29に新しいAPIを発表しました。無料版でツイートできる回数は、一か月に1500回までとなります。月額100ドルのプランでは、一か月に3000回までです。この回数は、ツイートだけでなくDMやリツイート、お気に入り登録なども1回としてカウントされますので、無料版では全然足りないどころか、有料版でも運用が難しいとの声が見受けられます。
今後30日間のあいだに新しいAPIに移行するよう呼び掛けており、その後は従来のAPIは廃止になるとのことです。
参考にさせていただいたサイト
本記事を作成するにあたり、参考にさせていただいたサイトは以下になります。
・GASでTwitterのAPIを使って投稿(ツイート)する
認証まわりのスクリプトについて、解説が分かりやすかったです。
・OAuth2、API v2でTwitter🐦にツイートできるようにしてみた(GAS)
無駄のない分かりやすい解説でした。初回認証で躓いたので大変参考になりました。
・Twitter Developersのフォーラム
サンプルコードを参考にしました。
・Apps Script OAuth2 のreadme
GASからOAuth2を利用する際の基本的な流れが書いてあります。
まとめ
今回は、Twitter APIとGASを利用してツイートをする方法について解説しました。私自身、TwitterのAPIを利用するのは初めてでしたので、既に使い込んでいる主人(prtn)に聞きながら、また、ネットの記事を参考にしながらなんとかツイートすることができました。
今後は、Twitter APIを利用して、ブログを更新したらお知らせツイートをしたり、GASのトリガー(定期実行)を使って過去の記事を紹介するツイートなどができたらいいなと思っています。
コメント
はじめまして!
GAS初心者の松田と申します。
このサイトに掲載のスクリプトをコピーしてテストしてみたのですが、認証用のmain()関数の実行時に下記のエラーになりました。
エラー内容
ReferenceError: OAuth2 is not defined
getService @Tweet_bot.gs:8
sendTweet @ninshou.gs:2
Tweet_bot.gsの8行目は以下になります。
return OAuth2.createService(‘twitter’)
サイト掲載のコード自体は何も変えてないのですが・・・
はじめまして!コメントありがとうございます。
記載いただいたエラーの原因は、CLIENT_ID、CLIENT_SECRETの中身を設定していないことが原因かと思います。
サンプルコードは、
const CLIENT_ID = ‘XXX’
const CLIENT_SECRET = ‘XXX’
となっていますが、これをご自身の環境に合わせて変更していただく必要があります。
こちらは、「Client ID・Client Secretの取得」の章にて取得方法を解説していますので、取得した値を入れて実行していただくと
正しく動くかと思います。
また試してみて不明点等ございましたらお気軽にコメントいただければと思います。
ご返信ありがとうございました!
ご指摘のライブラリ追加の件は、途中で気がついたので追加しております。
また、「記載いただいたエラーの原因は、CLIENT_ID、CLIENT_SECRETの中身を設定していないことが原因かと思います。」も、設定しておりますが反応がありません。
>実行する関数が「main」になっていることを確認して、「実行」を押します。
こちらの実行時、アプリへのアクセス許可の画面も表示されず、終わってしまします。
なかなかうまくいきませんね・・・
同じところで引っ掛かりました。
https://github.com/googleworkspace/apps-script-oauth2#setupに書いてあるように、OAuth2のライブラリを追加しないとですね。
コメントありがとうございます。
ライブラリの追加について、記載が抜けていました。ご指摘ありがとうございます!
記事に説明を追記しておきます。