Node.jsでTwitterAPIを叩いて、Lambdaに定期実行させる


定期ポストがしたくって、最近はNode.jsばっかりだったので、Javascriptで書いてみた。

環境は以下の通り。

```
$ node -v
v5.11.1
$ npm -v
3.8.6
```

まずは今回書いてみた全文を掲載。

```index.js
'use strict';

exports.handler = (event, context) => {
  let Twitter = require('twitter');

  let client = new Twitter({
    consumer_key: '',
    consumer_secret: '',
    access_token_key: '',
    access_token_secret: ''
  });

  let message = '【定期】ほげほげ';

  client.post('statuses/update', {status: message}, (e, tweet, res) => {
    if(e) {
      console.log(e);
      throw e;
    }

    console.log(tweet);
    console.log(res);
    
    context.done(null);
  });
}

```

## Twitter API Keyの取得
TwitterのAPIKeyやらはこちらから取得してください。
https://apps.twitter.com/


（どうやら、アプリを登録する際、自分のTwitterアカウントに電話番号を登録しておかなくてはならないらしい。昔はそんなこと無かった気がする。）

## 必要なモジュールを取得
今回はTwitterだけです。

```package.json
{
  "private": true,
  "dependencies": {
    "twitter": "^1.3.0"
  }
}
```

```
$ npm install
/Users/mac-user/www/twitter
└─┬ twitter@1.3.0
  ...
```

## 手動で実行してみる

```index.js
'use strict';

let Twitter = require('twitter');

let client = new Twitter({
 consumer_key: '',
 consumer_secret: '',
 access_token_key: '',
 access_token_secret: ''
});

let message = '【定期】ほげほげ';

client.post('statuses/update', {status: message}, (e, tweet, res) => {
 if(e) {
   console.log(e);
   throw e;
 }

 console.log(tweet);
 console.log(res);
});
```

手動で実行するのであれば、「exports.handler」は必要ないです。
これはLambdaで実行させるときに必要になります。

```
$ node index.js
```

responseの中身は結構あって、この例ではconsole.logですべて表示しようとしていますが、膨大なので特に出す必要も無いと思いました。

responseの例はこちらから
https://dev.twitter.com/rest/reference/post/statuses/update

## Lambdaに登録して、定期実行させてみる
初めてのLambdaだったので、手探り状態でした。

### 先ほど作ったファイルをLambda用に

```index.js
'use strict';

exports.handler = (event, context) => {
  let Twitter = require('twitter');

  let client = new Twitter({
    consumer_key: '',
    consumer_secret: '',
    access_token_key: '',
    access_token_secret: ''
  });

  let message = '【定期】ほげほげ';

  client.post('statuses/update', {status: message}, (e, tweet, res) => {
    if(e) {
      console.log(e);
      throw e;
    }

    console.log(tweet);
    console.log(res);
    
    context.done(null);
  });
}

```

Lambdaでは正常に処理が終了したということを明記する必要があるようです。
今回は「context.done(null);」がそれに当たります。

### zipに圧縮

Lambdaでは必要なモジュールを実行するコードと共に圧縮してアップロード、もしくはS3に設置して実行可能なようです。

今回はzipで圧縮して、アップロードしました。

```
$ zip -r index.zip index.js node_modules
```

### 登録
Step1でSelect blueprintがありますが、今回は使用しなかったので、Skip。

Step2では適当に名前を登録し、先ほど圧縮したファイルをアップロードします。この時、LambdaでNode.js 4.3を使用しました。ほかはデフォルトのままです。

*画像は登録後のもの

![スクリーンショット 2016-06-06 21.37.36.png](https://qiita-image-store.s3.amazonaws.com/0/27083/59ba91b4-0048-a9c6-e17a-fd7657228b8a.png "スクリーンショット 2016-06-06 21.37.36.png")

### テスト
左上にある「TEST」から実行してみます。今回は引数がないので、特になんでも構わないはずです。

ですが、これでは失敗してしまいます。

失敗した場合、下部とClowdWatchLogsに失敗した内容が書き込まれます。

```
Task timed out after 3.00 seconds
```

デフォルトのtimeoutは3秒で設定されていますが、どうやら3秒では短すぎるようでした。

10秒にして再テストします。

```
-control': 'no-cache, no-store, must-revalidate, pre-check=0, post-check=0',
        connection: 'close',
        'content-disposition': 'attachment; filename=json.json',
        'content-length': '2744',
        'content-type': 'application/json;charset=utf-8',
        date: 'Mon, 06 Jun 2016 12:44:37 GMT',
        expires: 'Tue, 31 Mar 1981 05:00:00 GMT',
        'last-modified': 'Mon, 06 Jun 2016 12:44:37 GMT',
        pragma: 'no-cache',
        server: 'tsa_a',
        'set-cookie': [Object],
        status: '200 OK',
        ...	
```

statusが200で返ってきました。成功したようです。

### Scheduled Eventを登録する

最後にScheduled Eventを登録します。
登録方法はEventの種類はいろいろありますが、今回は「CloudWatch Events」で登録します。

CloudWatch EventsはいわばCronのようなもので、Cromっぽい式でスケジュールを登録できます。

今回はこの様に登録しました。

![スクリーンショット 2016-06-06 21.57.09.png](https://qiita-image-store.s3.amazonaws.com/0/27083/6d2697c7-1764-33c3-a980-f46577258deb.png "スクリーンショット 2016-06-06 21.57.09.png")


CloudWatch Eventsの式は通常のCronの式より数が一つ多く、「年」を指定することが出来ます。

詳しくはこちらを。
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/DeveloperGuide/ScheduledEvents.html

この例は「毎日、3時45分」に実行するとなっていますが、これは「UTC」の時刻なので日本時間では「12時45分」です。

これで定期実行も登録されました。

## 嵌まったこと

定期ポストをしたかったのですが、Twitterの仕様上、全く同じツイートは出来ないという仕様がありました。ちなみに、全く同じツイートをした場合には以下のようにメッセージが返ってきます。

```
{ code: 187, message: 'Status is a duplicate.' }
```

そのままですけど、「ツイートの内容が一緒だぞ。」といわれ、失敗してしまうので、定期的に別のツイートをするか、ツイートにバリエーションを持たしておいた方がいいと思いました。