Now.shを使って15分でLINE Botをデプロイする

# TL;DR
「[わずか300円でIoTボタンを作る方法](https://qiita.com/vimyum/items/8b7548ca8cf45383c5b0)」の続きだよ。のんびりしていたら既にバックエンドまで実装済みの記事「[通知が飛ぶIoTボタンを作ってみた](https://qiita.com/a_halka/items/050e81f6ef09546f5c4b#_reference-b5da9c4c66b173a070c4)」があがってるけど、気にしないで続きを書くよ。今回はあまりIoTボタンとは関係ない内容なので、先に伝えたいことを書くよ。

 - Now.shはNode.jsが今すぐ簡単に使える素敵なPaaSだよ
 - 標準でHTTPSが使えるのでLINE Bot開発に最適だ
 - LINE Botをデプロイするには、`SECRETS`や`FROZEN`を考慮しよう

ちなみに先のIoTボタンからLINEに通知したいだけならBotを使わずに、LINE Notifyを使った方が簡単だよ。

# 準備 (LINE Messaging API利用登録）
まずはLINE Messaging APIの利用登録をするよ。LINE記事「[LINE BOTの作り方を世界一わかりやすく解説（１）【アカウント準備編】](https://qiita.com/yoshizaki_kkgk/items/bd4277d3943200beab26)」や、「[わずか5分。新LINE Messaging APIでbotを作ってみた手順全公開](https://bita.jp/dml/line-messaging-api-exp)」がわかりやすい！
これらの記事の手順にしたがって`Channel Secret`と`Channel Access Token`を入手しよう。 


# Now.sh
Now.shはNode.jsのアプリをとても簡単な動かせるPaaSだよ。アカウント作成からドメイン取得まですべて簡単なCLIコマンドでできる尖がったサービスだ。利用にあたってユーザ情報登録やトークン取得も不要で爆速だ。ただし、無料で使えるOSSプランの場合、下記２点は要注意だ。

 - **ソースコードは全て公開**されるよ。
 - データの永続化の仕組みは提供しないよ。

Qiitaにも紹介記事「[Now でクラウドの複雑さから解放されよう、今すぐに](https://qiita.com/aggre/items/f0cb9f8b8e8c54768e50)」があるので見てみよう。

# Now.shでLINE Bot
## 事前準備
Now.shで使えるNode.jsの最新バージョンは`8.0.0`だ(2017/10月現在)。Node.jsのインストール方法は省略！Now.shのCLIはnpmでインストールできるよ。

```bash
$ npm install -g now
```

Now.shは`package.json`があるディレクトリをPaaSにデプロイするよ。`package.json`を作成し、今回のアプリに必要なパッケージ(LINE SDKとExpress関連)もインストールだ。

```bash
$ mkdir myapp
$ cd myapp
$ npm -y init
$ npm install @line/bot-sdk express body-parser
```

アプリを起動するための設定をpackage.jsonに追加するよ。今回はアプリのファイル名を`index.js`にするよ。

```vim:package.json
〜略〜
"scripts": {
     "start": "node index.js",
 }
```

## コピペ＆デプロイ
LINE Botの本体`index.js`にはとりあえず[公式のサンプルEcho bot](https://github.com/line/line-bot-sdk-nodejs/blob/master/examples/echo-bot/index.js)をコピペするよ。

```js:index.js
'use strict';

const line = require('@line/bot-sdk');
const express = require('express');

const config = { 
    channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
    channelSecret: process.env.CHANNEL_SECRET,
};

const client = new line.Client(config);
const app = express();
    
app.post('/webhook', line.middleware(config), (req, res) => {
    Promise
        .all(req.body.events.map(handleEvent))
        .then((result) => res.json(result));
});

function handleEvent(event) {
    if (event.type !== 'message' || event.message.type !== 'text') {
        return Promise.resolve(null);
    }   
    const echo = { type: 'text', text: event.message.text };
    
    return client.replyMessage(event.replyToken, echo);
}

const port = process.env.PORT || 3000;
app.listen(port, () => {
    console.log(`listening on ${port}`);
});
```

あとは下記のコマンドでデプロイするだけだ。初回はメールアドレスの入力を求められるので、有効なメールアドレスを入力するよ。

```bash
$ now
> No existing credentials found. Please log in:
> We sent an email to XXX@gmail.com. Please follow the steps provided
  inside it and make sure the security code matches Suspicious Ant.
```

こんな感じのメールが届くのでリンクをクリックすれば認証は完了だ。

```text:mail
Hi!

Login attempt from XXXX, Japan
Verify that the provided security code matches Suspicious Ant before proceeding. 
Then please follow this link to verify your email address.
```

再び`now`コマンドを実行するとアプリがデプロイされるよ。

```bash
$ now
> Deploying ~/work/Now/linebot under XXX@gmail.com
> Using Node.js 8.4.0 (default)
> Ready! https://xxx-abcyezicoh.now.sh [1s]
> Synced 3 files (10.02KB) [14s]
> Initializing…
> Building
...
> Deployment complete!
```

コマンド実行時に画面に表示されたURLでアプリにアクセスできるよ。LINE BotはSSL証明書が必要だけど、Now.shはHTTPSで提供されるから問題なしだ。ポート番号はコード中では3000番で指定したけど、デプロイ後は80番でアクセスできるよ。

## Botのために
### URL固定
アプリのURLはデプロイのたびに変更されるんだ。LINE botのwebhookに指定するためにはデプロイバージョンに関わらず固定化されたURLを使いたいよね。Now.shではURLに好きなAlias(下の例では`https://myapp.now.sh`)をつけられるよ。

```
 $ now alias set https://xxx-abcyezicoh.now.sh myapp
```
他にも`package.json`に[aliasの設定をする方法](https://zeit.co/docs/features/configuration#"alias"-(string|array))もあるよ。

### アクセストークンなど秘密の情報
Now.shの無料プランではソースコードはすべて公開されてしまうよ。だからアクセストークンなどの秘密の情報をコードに直書きすることは絶対ダメだね。
これを解決するためにNow.shでは`Secrets`を提供しているよ。秘密の情報をNow.shに`Secrets`として保存しておき、`Secrets`と環境変数を対応づけてデプロイできるんだ。

```bash
$ now secret add line-toke XXXX-XXXX-XXXX
$ now secret add line-secret YYYY-YYYY-YYYY
$ now -e CHANNEL_ACCESS_TOKEN=@line-token -e CHANNEL_SECRET=@line-secret
```

上の例では、秘密の値(`XXXX-XXXX-XXXX`)を`line-token`として`Secrets`に登録し、これをアプリ内から環境変数`CHANNEL_ACCESS_TOKEN`としてアクセスできるようにしているよ。

### Keep-Alive
Now.shは、一定期間アクセスがないと`FROZEN`状態に入ってしまうよ。`FROZEN`状態でリクエストが来ると、ふたたび`READY`状態になりリクエストを受け付けるようになるけど、`FROZEN`状態時に来たリクエストは処理できないんだ。
だから`FROZEN`状態にならないように定期的にKeepAliveリクエストを送信しないといけないよ。
cron.dで定期的に`curl`を叩いてもいいし、IFTTTの`Date&Timer`と`Webhook`を利用しても良いね。

## 完成
これでLINE Botが完成だよ:raised_hands_tone2:　本題だった「IoTボタンからのリクエストに応じてBotでメッセージを通知」には、先ほどのEcho Botサンプルにちょっと手を加えればOKだ。

![button-line.gif](https://qiita-image-store.s3.amazonaws.com/0/160451/a7e8e15a-45de-f66b-dadb-54216f6cba0f.gif)

ソースコードは[GitHub](https://github.com/vimyum/linebot-for-nowsh)に上げておくよ。LINEグループに参加した際にグループIDを記憶し、WebAPIにリクエストが来たら記憶したグループID宛にメッセージを投げているよ。詳しい説明は[コード中](https://github.com/vimyum/linebot-for-nowsh/blob/master/index.js)にコメントで書いておくよ。