動機
毎日自動でTwitterの名前を変えたかった。
要件
- ある1ユーザーのTwitterの名前を毎日0時に自動で変更したい
前提知識
- TwitterAPIはOAuth認証を用いる
- OAuthは現在主に用いられているバージョンとして1.0aと2.0の2つがある
- 単なるバージョン違いという訳ではなく、認証の仕組みから違うため、別物である(互換性がない)
- TwitterAPIではOAuth2.0での認証は一部のAPIしか対応していないため、1.0aを使う
- TwitterではOAuth2.0を使う認証をApplication-only authentication、1.0aを使う認証をApplication-user authenticationと呼んでいる
- Oauth with the Twitter API — Twitter Developers
TwitterAPIの利用準備
TwitterAPIを用いるには開発者申請が必要。
Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ ※2018年9月時点の情報 - Qiita
GASでTwitterAPIを使う方法
公式でGASでOAuth1.0a認証をやるためのライブラリがあるのでそれを使う。
https://github.com/gsuitedevs/apps-script-oauth1
ちなみにOAuth2.0用のライブラリも存在するが、そもそもの認証の仕組みが違うので、1.0aには使えないため注意。
1. ライブラリを導入する
README.mdに書かれている通りに進める。
GASのメニューから「リソース」->「ライブラリ」を選択し、以下のプロジェクトキーを入力し「追加」を押す。
1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s
バージョンはとりあえず最新のものを選んでおけば良さそう。
2. TwitterのAppにリダイレクトURLを設定する
リダイレクトURLはhttps://script.google.com/macros/d/{SCRIPT ID}/usercallback
という形式になる。
スクリプトIDはGASのメニューから「ファイル」->「プロジェクトのプロパティ」で確認できる。
TwitterのAppの設定を開き、CallbackURLに設定する。
3. 対象ユーザーのアクセストークンを取得する
まず以下のようなスクリプトを用意する。
// Twitter AppのConsumer Api Key
var CONSUMER_KEY = "*****";
var CONSUMER_SECRET = "************";
// 認証URLを取得しログに出力する
function logAuthorizeUri() {
var twitterService = getTwitterService();
Logger.log(twitterService.authorize());
}
// OAuth認証をよしなにしてくれるサービスクラスのインスタンスを生成・取得する
function getTwitterService() {
return OAuth1.createService('Twitter')
.setAccessTokenUrl('https://api.twitter.com/oauth/access_token')
.setRequestTokenUrl('https://api.twitter.com/oauth/request_token')
.setAuthorizationUrl('https://api.twitter.com/oauth/authenticate')
.setConsumerKey(CONSUMER_KEY)
.setConsumerSecret(CONSUMER_SECRET)
// リダイレクト時に実行されるコールバック関数を指定する
.setCallbackFunction('authCallback')
// アクセストークンを保存するPropertyStoreを指定する
.setPropertyStore(PropertiesService.getUserProperties());
}
// リダイレクト時に実行されるコールバック関数
function authCallback(request) {
var twitterService = getTwitterService();
// ここで認証成功時にアクセストークンがPropertyStoreに保存される
var isAuthorized = twitterService.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success');
} else {
return HtmlService.createHtmlOutput('Denied');
}
}
CONSUMER_KEY,CONSUMER_SECRETはTwitterAppの設定画面から確認できる。
認証手順
logAuthorizeUriを実行し、認証URLを取得する。
ログにURLが出力されているので、メニューの「表示」->「ログ」からログを表示し、URLをコピーしてアドレスバーに貼って直接アクセスする。
(普通のTwitterアプリだと自動で移動するが、GASのstandalone scriptだとそれができないためこういった形になる)
アクセスするとTwitterの認証画面が出るので、認証ボタンを押す。
リダイレクトされて以下のような画面が出れば成功。
一度認証を行うと、Twitter側で認証を解除しない限り同じアクセストークンが使える。
アクセストークンはPropertyStore上に保持されているため、認証が解除されない限りこの手順をもう一度行う必要は無い。
参考:GASで永続化する方法まとめ(設定や処理結果を保存・読み込みしたい時) - Qiita
4. TwitterAPIを叩く
以降はOAuthのライブラリがよしなにしてくれるので、難しいことを気にせずともAPIを叩くことができる。
例えば名前を変更したいなら以下のような感じ。makeRequestとchangeNameが肝。
API:POST account/update_profile — Twitter Developers
// 名前を今日の日付に変更する
function changeTodayName()
{
var todayName = getTodayName();
changeName(todayName);
}
// 今日の名前を取得する
function getTodayName()
{
// TODO: 日によってちゃんと変わるように実装する
return "テスト";
}
// Twitterに名前変更のリクエストを送る
// name: 変更したい名前
function changeName(name)
{
makeRequest("account/update_profile.json", {"name": name});
}
// TwitterにAPIリクエストを送る
function makeRequest(api_url, parameters) {
var twitterService = getTwitterService();
if (twitterService.hasAccess()) {
var url = 'https://api.twitter.com/1.1/' + api_url;
var response = twitterService.fetch(url, {
method: "post",
muteHttpExceptions: true,
payload: parameters
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
} else {
Logger.log(service.getLastError());
}
}
changeTodayNameを実行すると名前が「テスト」に変わることが確認できる。
5. 毎日0時にトリガーを設定する
毎日0時に名前を変更するために、自動で実行するための設定を行う。
メニューの「編集」->「現在のプロジェクトのトリガー」から設定画面に移行し、右下の「トリガーを追加」ボタンを押す。
よしなに設定を行い、「保存」で終了。
日付ベースの設定だと分単位で指定できないので、厳密に0時0分に変更したい場合には分ベースで1分単位で実行し、スクリプト側で時間判定を行ってAPIを叩くのが良さそう。
まとめ
- TwitterAPIはOAuth1.0aが標準であり、2.0では一部APIしか使うことができない(2019/03現在)
- GASでOAuth認証を行うためのライブラリが公式で用意されている
- GASにはPropertiesServiceというデータ永続化のための便利クラスがあり、そこにアクセストークンを保持することで認証状態を保持できる
OAuth1.0aと2.0で情報が錯綜しているのと、GASでTwitterAPIを使うスクリプトは各所にあるものの、動作原理が解説されておらずいまいち理解できなかった(特にアクセストークンがどこに保持されるのかわからなかった)ので、少し苦労しました。
スプレッドシートと連携したりすればもっと色々できると思います。