TwitterのAccount Activity APIとwebhookを使用する

# はじめに

TwitterのwebhookとDMを使った簡単な自動応答Botを作ろうとしたら、その下準備だけでかなり面倒だったので、その手順を記録がてら残しておきます。なお、ここでは最近無料利用もできるようになったAccount Activity APIを使用しています。

# 開発者アクセスとWebアプリの準備

## 開発者アクセス権の登録
Account Activity APIを使用するには、アクセス権の登録が必要です。そこでまず https://developer.twitter.com/en/apply で必要な登録を行います。なお、登録画面は今のところ英語版しか用意されていないようです。

1. 開発者アクセスを取得するTwitterアカウントを選択して「Continue」
2. アクセスのタイプについて聞かれるので、「個人利用」（２つある選択肢のうちの下の方）を選択
3. アカウント名と主な所在地（国）についての入力欄が表示されるのでそれぞれ入力
4. プロジェクトについての説明画面では、まず関連する関心項目（学術調査や顧客エンゲージメントなど）にチェックを入れる。個人利用だと「Topic analysis（トピックの分析）」や「Trend and event detection（トレンドやイベントの検出）」あたりでしょうか。
5. その下の入力欄に、作成するWebアプリについての説明（ **英文** 300字以上）を入力。
6. 画面の一番下では、作成したアプリがTwitterから得たデータを行政機関等にを提供するかどうかを選択（基本的にこれは「No」でよい）

英語で300字以上の説明がやや手間かもしれませんが、申請内容に問題がなければ数日以内に登録完了のメールが来ると思います。

# アプリの登録
開発者アクセスの審査を待っている間に、https://apps.twitter.com でAccount Activity APIで使用するアプリの登録を行います。このとき、DMを扱えるようにアプリのアクセスレベルを設定しておきます（read、write、direct messagesのすべてを許可）。

自作アプリの登録手順についてはWebで検索すればいくつも出てくるので、ここでは省略します。

# 開発環境の登録
開発者アカウントが承認されると開発用ダッシュボードにアクセスできるようになります。無料のPremiumアカウントでは、30日分のツイートの検索、フルアーカイブの検索、Account Activity API（いずれもSandbox）の環境がそれぞれ１つずつ設定できるようになっています。

Account Activity APIを使用するために当然ながらAccount Activity APIの環境を作成しなくてはなりません。「set up dev environment」を選択して必要事項の登録を行います。なお、このときに指定する開発環境名（dev environmental label）が、APIにアクセスする際のurlの一部となります。

# Webアプリの設定

今回は、webhookを扱うためのWebアプリを[glitch](https://glitch.com)というサイトでnode.jsを使用して作成することにしました。いくつか制限はありますが、基本的に無料で使用でき、またコードを修正するとそれがすぐさま自動でサーバに反映されるので、webhook処理用のちょっとしたアプリを作成するにはちょうど良い感じです。glitchでは「hello-express（基本Node.jsアプリ）」のテンプレートを使用して新規プロジェクトを作成します。


## Webアプリの設置

WebアプリでTwitterのwebhookを使用するためには、Twitter Challenge Response Check (CRC) と呼ばれるテストに合格しなくてはなりません。そこでまず、Webアプリの方でこれに対応するための準備をします。

CRCでは、Twitterからwebhookのアドレスに対してGETによるアクセスが行われ、適切なHMACが得られるかどうかの確認が行われます。HMACは、GETアクセス時に提供されるCRCトークンとアプリのコンシューマーシークレットに基づいて作成しなければなりません。このテストに合格しない限り、Account Activity APIでwebhookを使用することはできません。また、[CRCに関するドキュメント](https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/guides/securing-webhooks)によれば、このチェックはwebhookの設置の際だけでなく、ほぼ毎時間ごとにurlの妥当性検証に使用されるようです。

これらのことから、Webアプリには次のような処理を記述しておきます。ここでは、webhookのアドレスは「http://ドメイン名/webhook」であるものとします。なお、glitchでは基本的にコードは他のユーザーから丸見えになりますので、コンシューマーキーなどの秘密情報は「`.env`」というファイルに記述したうえで使用します。この「.env」で設定した定数や変数を使用する場合には、`process.env.変数名`という形でコード中に記述します（`.env`の中身は他のユーザーからは見えません）。

```javascript
// Twitter Challenge Response Checkに対処する
const crypto = require('crypto');

app.get("/webhook", function (request,response) {
  var hmac = crypto.createHmac('sha256', process.env.[コンシューマーシークレット]).update(request.query.crc_token).digest('base64');
  response.send('{"response_token":"sha256='+hmac+'"}');
});
```

# Webhookの登録・設定作業
## Webhookの設置

TwitterからのwebhookそのものはPOSTによるアクセスですので、webhookアドレスへのPOSTアクセスを処理できるようにしておきます。

```javascript
// webhookの処理
app.post("/webhook", function (request, response) {
  response.setHeader('Content-Type', 'text/plain');

  ... ここに処理（最初は空でも問題ない） ...

  response.sendStatus(200);
});
```
これでようやくTwitterにwebhookを登録する準備が整いました。

## Webhookの登録

Account Activity APIでwebhookを使用するためには、webhookアドレスをtwitterに登録しなくてはなりません。無料Premiumアカウント（変な響き……）で登録できるwebhookアドレスは１つだけです（詳細については[公式ドキュメント](https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/overview)参照）。

Twitterへのwebhookアドレスの登録は

```
https://api.twitter.com/1.1/account_activity/all/開発環境名/webhooks.json?url=webhookアドレス
``` 

へのPOSTで行います。ここで、「開発環境名」はAccount Activity APIを登録したときに設定した開発環境名、`url=`以降にはwebhookのアドレス（https://ドメイン名/webhook）をパーセントエンコードしたものを使用します。たとえば、開発環境名が「myenv」、webhookアドレスが「https\://mydomian.com/webhook」なら、

```
https://api.twitter.com/1.1/account_activity/all/myenv/webhooks.json?url=http%3A%2F%2Fmydomian.com%2Fwebhook
``` 

がアクセス先のurlとなります。

このアドレスへのアクセスには、OAuth1.0による認証を使用します。CRCと違い、webhookの登録自体は基本的に一度きりのものなので、[Postman](https://www.getpostman.com/)や[Insomnia](https://insomnia.rest/)などのWeb APIツールを使用するのがいいでしょう。OAuth認証に必要なタイムスタンプやシグニチャ等は、これらのツールが自動で処理してくれます。

下の画面は、Insomniaによるアクセスの場合です。

![webhook.png](https://qiita-image-store.s3.amazonaws.com/0/106317/01dd6fff-aae4-3454-1191-2e05f6ce29d9.png)

アクセスタイプを`POST`にし、先ほどのurlとアプリのCONSUMER_KEYやACCESS_TOKENなどを入力して送信します（必要なキーは http://apps.twitter.com で確認可能）。

このとき、webhookに対するCRCテストが行われれ、これに合格できない場合には`Webhook URL does not meet the requirements`というエラーが返されます。

webhookの登録が完了すると、webhookのidや作成日時などの情報が返されます。

## Webhookにユーザーを登録する
Webhookを設置しただけではまだ何も起こりません。このwebhookを使用してさまざまなイベントを処理するためには、イベントを取得するユーザー（自分自身）をwebhookに登録する必要があります。無料Premiumアカウントでは15ユーザーまで登録できるようです（[公式ドキュメント](https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/guides/managing-webhooks-and-subscriptions)参照）。

ユーザーの新規登録は以下のurlに認証情報と併せてPOSTすることで行います（[公式ドキュメント](https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/api-reference/aaa-premium#post-account-activity-all-env-name-subscriptions)）。Webhookの登録と同様に、OAuth1.0認証を使用します。

```
https://api.twitter.com/1.1/account_activity/all/開発環境名/subscriptions.json
```

これでようやく、DM受信や入力中といったAccount Activityのイベントでwebhookが投げられるようになります。