TwitterのAccount Activity API使ってみた①

# What's this?
Twitterから提供されているAccount Activity APIを利用して個人で利用しているTwitterアプリのデータをAPI経由で取得するための手順をまとめた記事です。この記事ではデータ取得の前段であるwebhook URLの登録までの手順をまとめています。


# Account Activity APIとは？
webhookを介してアカウントに関連するアクティビティをリアルタイムに検知してデータ取得ができます。

- 取得可能なデータの例
    - ツイート
    - いいね
    - RT(引用RT)
    - リプライ
    - メンション
    - フォロー(アンフォロー)
    - DM

PremiumプランのSandboxの範囲であれば無料で利用可能です。
詳細は[Twitter公式のドキュメント](https://developer.twitter.com/en/docs/twitter-api/enterprise/account-activity-api/overview)を参照してください。

# 全体構成
今回は下記構成でデータの取得と保存を目指します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/5d160c9b-1bd5-9003-4e99-87a055be663a.png)


# webhook URLの作成
Account Activity APIのアクティビティデータを受信するには、Twitterから定期的にGETリクエストされるCRCリクエストに対してレスポンストークンを返す必要があります。

- レスポンストークンの必要要件([ドキュメント](https://developer.twitter.com/en/docs/twitter-api/enterprise/account-activity-api/guides/securing-webhooks))


> ・A base64 encoded HMAC SHA-256 hash created from the crc_token and your app Consumer Secret
・Valid response_token and JSON format.
・Latency less than 3 seconds.
・200 HTTP response code.

そのため、GETリクエストの受け口になるwebhook URLとレスポンストークンを返すLambdaを作成します。


### レスポンストークン用のLambdaの作成
node.jsのLambda関数を作成します。

ランタイム:Node.js 12.x

```javascript
exports.handler = async(event, context, callback) => {
  // パラメータのcrc_token取得
  var response_token = null;
  if (event.queryStringParameters){
      var crc_token = event.queryStringParameters.crc_token;
      // ハッシュ化
      var crypto = require('crypto');
      var hmac = crypto.createHmac('sha256', process.env['CONSUMER_SECRET']).update(crc_token).digest('base64');
      console.log(`receiving crc check. token=${crc_token} res=${hmac}`)
      var calculatedSignature = 'sha256=' + hmac;
      response_token = calculatedSignature;
  }
  const response = {
      statusCode: 200,
      body: JSON.stringify({'response_token': response_token}),
  };
  return response;
};
```

- `process.env['CONSUMER_SECRET']`の環境変数についてはTwitter Developer Account開設後に設定します。

### APIGatewayでGETメソッドの作成

次にTwitterからのGETリクエストを受け取るwebhook URLをAPIGatewayで作成します。

- APIタイプをREST APIとして新規APIを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/3bd8af7e-c3e8-758c-0f2f-0c62b66ab7ec.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/a1a3c694-f640-d629-8b04-1ac55854949a.png)

- GETメソッドの作成
    - 統合タイプ:Lambda関数
    - Lambdaプロキシ統合の使用：チェック
    - Lambda関数:{先ほど作成したLambda関数}
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/11087b30-fcb0-34ff-0979-5c109c740119.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/eab17356-5731-c8b4-43f5-e22cdc570047.png)

- CORSの有効化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/167f37af-6a50-c911-ca2b-ae5c5c0dd911.png)

Access-Control-Allow-Originを「*.twitter.com」に変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/2ae83fcd-5b0a-65f0-c4fc-d1ceccb68151.png)

- デプロイ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/a9ebcdbd-050b-47d8-50e4-a13f452eb6e6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/b1a3d07f-1526-b602-030e-04b1ff7e3dd4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/57d47eed-bcac-a25d-93e0-499bea1d6ce1.png)

無事デプロイがされるとステージが作成され、API呼び出しURLが生成されます。
このURLがwebhook URLとなります。


# Twitter Developer Account の申請と設定
### アカウントの申請
Account Activity APIを利用するにはTwitterのDeveloper Accountが必要になるためアカウントの申請を行います。

[こちらのページ](https://apps.twitter.com/)から[Create an app]ボタンを押すと申請ページに遷移します。

申請フォームは全て英語になりAPIの使用目的などを聞かれるので、頑張って英語で記入し申請します。

申請が完了すると登録したメールアドレス宛に申請完了メールが届きます。

場合によってメールで追加の確認事項がくる場合があるのでめげずに英語で回答します。
僕の場合、承認まで2回ほどメールでの確認がありました。

承認まで2週間ほどかかりましたが、もっと早く承認される人もいるようです。

無事承認されるとDeveloper Accountからアプリの作成が可能になり、APIも利用可能になります。

### 基本設定
- アプリケーションの登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/9049d063-1533-b34d-96d1-9eead1cb501e.png)

- アクセストークンの取得
既に作成済のためキャプチャでは[Regenarate]になっていますが、初回は[create]になってると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/f042aede-1a6b-305f-b8dd-b2dead9b3b6a.png)

- 作成された下記4つのkeyは大切に保管して置いてください
    - API key
    - API secret key
    - Access token
    - Access token secret

- パーミッションの設定
  - アプリのパーミッション設定を「Read + Write + Direct Messages」に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/482965c5-c9f6-5fad-4163-d73547d337cc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/c77229e5-e95d-d5df-7861-6af7f6601222.png)

- 認証設定
    - APIGatewayの章で作成したwebhook URLを設定します。
「Callback URLs」「Website URL」どちらも同一URLで問題ないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/ad5dce0f-c200-7792-4ade-1035af60f084.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/6a1e5e28-88af-9b5e-03d8-6203b67b72ba.png)

- Account Activity APIのセットアップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/b5a2180b-18bc-10a5-cb4b-13e6206787fe.png)

これでTwitter Developer Accountの初期設定は完了です。

### Lambda関数に環境変数を追加
事前に作成したLambda関数に環境変数を追加します。
- 作成した`API secret key`をLambda関数の環境変数に追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566229/e0c258fb-a5c6-9f7c-4b95-758133b885cd.png)


# webhook URLの登録
最後にwebhook URL登録作業を行います。
[こちら](https://developer.twitter.com/en/docs/twitter-api/enterprise/account-activity-api/guides/managing-webhooks-and-subscriptions)のドキュメントを参考に進めていきます。

本来そこまで難しい作業ではないはずなのですが、中々うまくいかず最終的にnode.jsでスクリプトを作成し実施しました。

### nodeスクリプトの環境構築
まずはnodeスクリプト実行に必要な環境を作ります。

```
// nodejsインストール
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

//バージョン確認
node -v
npm -v  

//初期化
npm init

//require,requestのインストール
npm install require --save
npm install request --save
```

これで環境構築は完了です。

### 環境変数の準備
プロジェクト配下のルートディレクトリに`config.json`ファイルを作成し、必要な環境変数を設定します。

```config.json
{
  "TWITTER_CONSUMER_KEY": "①",
  "TWITTER_CONSUMER_SECRET": "②",
  "TWITTER_ACCESS_TOKEN": "③",
  "TWITTER_ACCESS_TOKEN_SECRET": "④",
  "devLabel": "⑤",
  "webhookUrl": "⑥"
}
```

①-④の情報はTwitter Developer Account作成時に発行されたアクセストークンを設定します。
⑤:APIGatewayで作成したステージ名
⑥:APIGatewayで作成したwebhook URLを設定


### webhook URLの登録とwebhook_idの取得

webhook URLを登録するための`Twitter_register_webhook.js`を作成します。

```Twitter_register_webhook.js
// webhook URLの登録コード
const request = require('request');
const config = require(`./config.json`);

const twitter_oauth = {
  consumer_key: config.TWITTER_CONSUMER_KEY.trim(),
  consumer_secret: config.TWITTER_CONSUMER_SECRET.trim(),
  token: config.TWITTER_ACCESS_TOKEN.trim(),
  token_secret: config.TWITTER_ACCESS_TOKEN_SECRET.trim()
}

const request_options = {
  url: `https://api.twitter.com/1.1/account_activity/all/${config.devLabel}/webhooks.json`,
  oauth: twitter_oauth,
  headers: { 'Content-type': 'application/x-www-form-urlencoded' },
  form: { url: config.webhookUrl }
};
request.post(request_options, (error, response, body) => { console.log(body) });

```

実行します。

```
node Twitter_register_webhook.js
```

成功するとレスポンスでwebhook_idが返ってきます。
このidは今後必要になるのでメモしておきます。

これでwebhook URLの登録は完了です。


### webhookにユーザーアカウントの追加

最後です。
登録したwebhook URLにユーザーアカウントを追加するための`Twitter_add_subscription.js`を作成します。

```Twitter_add_subscription.js
//Twitter_add_subscription.js
// アカウント追加のコード

const request = require('request');
const config = require(`./config.json`);

const twitter_oauth = {
  consumer_key: config.TWITTER_CONSUMER_KEY.trim(),
  consumer_secret: config.TWITTER_CONSUMER_SECRET.trim(),
  token: config.TWITTER_ACCESS_TOKEN.trim(),
  token_secret: config.TWITTER_ACCESS_TOKEN_SECRET.trim()
}

const request_options = {
  url: `https://api.twitter.com/1.1/account_activity/all/${config.devLabel}/subscriptions.json`,
  oauth: twitter_oauth
};
request.post(request_options, (error, response, body) => { console.log(`${response.statusCode} ${response.statusMessage}`); console.log(body) });

```

実行します。

```
node Twitter_add_subscription.js
```

`204 No Content`と返ってくればOKです。

以上で完了です。
これでようやくAccount Activity APIを利用してデータ取得ができる準備ができました。
次の記事では実際にデータを取得してDynamoDBにデータを保存する手順を紹介します。