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

認証手順

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

参考資料