Edited at

[GAS] GoogleAppsScriptでTwitterbotを作る


動機

毎日自動でTwitterの名前を変えたかった。


要件


  • ある1ユーザーのTwitterの名前を毎日0時に自動で変更したい


前提知識


  • TwitterAPIはOAuth認証を用いる

  • OAuthは現在主に用いられているバージョンとして1.0a2.0の2つがある


    • 単なるバージョン違いという訳ではなく、認証の仕組みから違うため、別物である(互換性がない)



  • TwitterAPIではOAuth2.0での認証は一部のAPIしか対応していないため、1.0aを使う




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の設定画面から確認できる。

image.png


認証手順

logAuthorizeUriを実行し、認証URLを取得する。

ログにURLが出力されているので、メニューの「表示」->「ログ」からログを表示し、URLをコピーしてアドレスバーに貼って直接アクセスする。

(普通のTwitterアプリだと自動で移動するが、GASのstandalone scriptだとそれができないためこういった形になる)

アクセスするとTwitterの認証画面が出るので、認証ボタンを押す。

リダイレクトされて以下のような画面が出れば成功。

一度認証を行うと、Twitter側で認証を解除しない限り同じアクセストークンが使える。

アクセストークンはPropertyStore上に保持されているため、認証が解除されない限りこの手順をもう一度行う必要は無い。

参考:GASで永続化する方法まとめ(設定や処理結果を保存・読み込みしたい時) - Qiita


4. TwitterAPIを叩く

以降はOAuthのライブラリがよしなにしてくれるので、難しいことを気にせずともAPIを叩くことができる。

例えば名前を変更したいなら以下のような感じ。makeRequestchangeNameが肝。

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を使うスクリプトは各所にあるものの、動作原理が解説されておらずいまいち理解できなかった(特にアクセストークンがどこに保持されるのかわからなかった)ので、少し苦労しました。

スプレッドシートと連携したりすればもっと色々できると思います。


参考資料