GCEからLINEのMessaging APIを使ってみる

# Introduction
ぼくはLINEが好きじゃないです．どちらかと言えばSlackを使いたいと思うタイプの人間なのです．
ところが，ぼくの周りにはLINEを多用してやまない人たちがたくさんいます．彼らと共に作業をこなすために，`/remind`等が使えるbotを作りました．

今回はそのデモを行ってみたいと思います．
恥ずかしいことにぼくはこの道のプロではないので，至らない点は数多くあると思います．ご了承ください．(身内で使うものなんて，動けばなんだって良い．そう思いますよね？)

# Environment
UbuntuとNode.jsを使います．

# Procedure
さて，では実際の手順を書いていきたいと思います．

## Create an instance
[Compute Engine](https://console.cloud.google.com/compute)からインスタンスを作りましょう．USリージョンのf1-microは1つまで常時無料らしいです．
ここではUbuntu 16.04 LTSを選びます．HDDは30GBまで無料だったはずなのでそうします．

ポイントとしてはトラフィックを許可することと，静的な外部IPを設定するくらいでしょうか．
SSH接続ができるようにしておいてください．

## Install Node.js, Nginx, Certbot and MongoDB
早速インスタンスに接続してください．

```bash
$ sudo apt-get install build-essential nodejs npm -y
$ sudo npm install n -g
$ sudo n lts
$ sudo apt-get purge nodejs npm -y
$ sudo apt autoremove -y
```

として，Node.js LTSをインストールします．nが嫌な人は他のものをお使いください．
(参考: [Ubuntuに最新のNode.jsを難なくインストールする - Qiita](https://qiita.com/seibe/items/36cef7df85fe2cefa3ea))

次に，

```bash
$ curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add -
$ VCNAME=`cat /etc/lsb-release | grep DISTRIB_CODENAME | cut -d= -f2` && sudo -E sh -c "echo \"deb http://nginx.org/packages/ubuntu/ $VCNAME nginx\" >> /etc/apt/sources.list"
$ VCNAME=`cat /etc/lsb-release | grep DISTRIB_CODENAME | cut -d= -f2` && sudo -E sh -c "echo \"deb-src http://nginx.org/packages/ubuntu/ $VCNAME nginx\" >> /etc/apt/sources.list"
$ sudo apt-get update
$ sudo apt-get install nginx -y
```

として，Nginxをインストールします．
(参考: [Ubuntuに最新のnginxをインストールする - Qiita](https://qiita.com/hiroq/items/420424bc500d89fd1cc8))

```bash
$ sudo apt-get update
$ sudo apt-get install software-properties-common -y
$ sudo add-apt-repository ppa:certbot/certbot -y
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx -y
```

として，Certbotをインストールします．ただし，証明書はまだ取得しないでください．まだドメインがないので出来ないのです．
(参考: [Nginx on Ubuntu 16.04 (xenial) - Certbot](https://certbot.eff.org/#ubuntuxenial-nginx))

```bash
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
$ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
$ sudo apt-get update
$ sudo apt-get install mongodb-org -y
$ sudo systemctl enable mongod
$ sudo systemctl start mongod
```

として，MongoDBをインストールします．
(参考: [Install MongoDB Community Edition on Ubuntu - MongoDB](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu))

ここまで，そしてこの先についても，適宜

```bash
$ sudo reboot
```

してください．少なくとも手順に従っていてエラーに出会うことはないはずなので，**困ったら再起動**です．

## Get a free domain
ドメインを取得します．もちろん無料じゃなくても良いですが，今回は[Freenom](http://freenom.com)を使うことにします．

ここでは`qiita.ga`を取得しました．

## Edit /etc/nginx/conf.d/default.conf
正直，この辺は本当に理解していないので参考程度にしてほしいです．ネスペの友人に助けてもらいたいくらい．

```bash
$ sudo vim /etc/nginx/conf.d/default.conf
```

として，3行目の`localhost`を今しがた取得したドメインに書き換えてください．ここでは`qiita.ga`です．

```bash
$ sudo certbot --nginx
```

として，ようやく証明書を取得します．英語の質問に頑張って答えてくださいね．

これでhttpsが使えるようになったはずです．LINEのWebhookにはセキュアさがマストなのです．

## Write code
さて，コーディングを始めましょう．と言いたいところですが，面倒なのでリポジトリを用意しました．boilerplateとは名ばかりで，中身は雑です．

```bash
$ git clone https://github.com/shamofu/line-bot-boilerplate.git
$ cd line-bot-boilerplate
$ npm install
```

コードを実行する前に，`.env`ファイルを埋めましょう．
`MONGODB_URI`は次の操作で得られます．

```bash
$ mongo
MongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.3
...
> exit
```

この場合，`MONGODB_URI`は`mongodb://127.0.0.1:27017/reminder`としてください．

`CHANNEL_`で始まる値はMessaging APIのChannel基本設定から得られます．
`CHANNEL_SECRET`は`基本情報>Channel Secret`，`CHANNEL_ACCESS_TOKEN`は`メッセージ送受信設定>アクセストークン（ロングターム）`です．

さて，設定を閲覧したついでに，Webhookを設定しておきましょう．
ここでは，`メッセージ送受信設定>Webhook URL`を`https://qiita.ga/line/webhook`とします．`https://(domain)/line/webhook`です．

## Launch bot
それではbotを起動しましょう！今回はpm2を使います．

```bash
$ sudo npm install pm2 -g
$ sudo pm2 startup
$ sudo pm2 start main.js --watch --name=line-bot
$ sudo pm2 save
```

これでインスタンスを再起動しても自動でbotが立ち上がるようになりました．

あとはNginxにbotを認識させるだけです．

```bash
$ sudo vim /etc/nginx/conf.d/default.conf
```

より，

1. upstreamを定義
2. proxyを設定

します．
(参考: [nginxでリバースプロキシ - Qiita](https://qiita.com/ogwmtnr/items/03996d3798facbc600da#nginx-%E3%81%A7%E3%83%AA%E3%83%90%E3%83%BC%E3%82%B9%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7))

まず1番．`server`ブロックの上に

```bash
upstream line-bot {
    server localhost:1124;
}
```

を追記してください．

そして2番．

```nginx
location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
}
```

の下に，

```nginx
location /line {
    proxy_pass http://line-bot;
}

proxy_redirect                      off;
proxy_set_header Host               $host;
proxy_set_header X-Real-IP          $remote_addr;
proxy_set_header X-Forwarded-Host   $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
```

を追記してください．

## Congratulations!
さあ，botを友だちに追加して，こう話しかけてみてください．

```
/remind
簡単なのだ！
イエオイア！
in 10 seconds
```

10秒後に想像通りのメッセージを受信するはずです．
最初の行でコマンドを指定，最後の行で日時を指定します．
日時には`in an hour | 3/9 | 3:34 | ...`などなど使えます．(参考: [chrono-node - npm](https://www.npmjs.com/package/chrono-node))

# Summary
お疲れ様でした．最初は各々の意味を理解するのに苦労するかもしれませんね．
ですが，思ってたより難しくなかったのではないでしょうか．

自作したbotを友人たちに使ってもらえると嬉しいですね！(一方，万が一にもデータベースをふっ飛ばしたときには...ﾜﾅﾜﾅ)