Line botをスマホでプログラミングできるようにしてみた

## モチベーション

Line botでも作ろうかなと思って、GAS(google apps script)を使うとサーバー持たずに簡易DB（スプレッドシート）込みで作れると知った時、**GASはウェブエディタだし実行環境はLINEだし、全部スマホで作れるのでは**と思ったら**作れなかった※1**ので**作れるようにした話※2**。

※1・・・GASのウェブエディタはスマホのブラウザをサポートしていなかった。
※2・・・結局のところ、GASのスクリプトをgithubで管理して、スマホ上で編集＆コミットすると（githubはスマホでもPC版サイトモードにすると使える）CircleCI経由でclaspを使って自動的にデプロイされるようにするよという話

## 前提
* PC開発環境はMac
* 最近のバージョンのnode&npm環境が整っている
* スマホはiPhoneで確認している

という前提で書かれています。
なんとなくわかっている人向けの簡易版手順を最後に載せていますので、なんとなくわかっている人はそちらを参照。

## 環境準備（PC編）

環境構築もスマホで完結させたかったけど一部のID情報取得や権限許可のUI操作がややこしそうだったので、初期設定はPCで。

### claspのインストール&ログイン

まずはGASをCLIで操作できるclaspの環境を準備します。

```
$ npm i @google/clasp -g
```

続いてclaspでログインします。

```
$ clasp login
```

このコマンドを実行すると、ブラウザが立ち上がりgoogleアカウントの選択と権限許可の画面が表示されます。画面の指示に従ってログイン処理を終えてください。

### GASプロジェクトの作成

```
$ mkdir testbot
$ cd testbot
$ clasp create 
## 作成するGASプロジェクトのtypeが聞かれるので`webapp`を選択。
```

正常に動作すれば、`appscript.json`というマニフェストファイルが生成されます。マニフェストに、LINEbotからのwebアクセスやMessegingAPIを使用するのに権限を追加しておきます。

```appsscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "webapp": {
    "access": "ANYONE_ANONYMOUS",
    "executeAs": "USER_DEPLOYING"
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": ["https://www.googleapis.com/auth/script.external_request"]
}
```

スプレッドシートの編集やdriveへのアクセスを行うなら、`oauthScopes`に`https://www.googleapis.com/auth/spreadsheets`とか、`https://www.googleapis.com/auth/drive`を加えておきましょう。
※不必要な権限を与えると危険性が高まるので理解した上で追加しましょう。本来、該当のコードが追加された際に承認を求められるのでウェブエディタで操作している分には不要です。

続いてメインのスクリプトを追加します。

```
$ touch bot.js
```

bot.jsの中身は後ほど作っていきますので、現時点では中身はなくてもOKです。

### GASプロジェクトの公開
ここで一連のファイルをGASプロジェクトにpushします。

```
$ clasp push
## Manifestを上書きしますか？と聞かれますが`y`で。
```

ここまで来たら、一度GASのウェブエディタを開きます。

```
$ clasp open
```

ブラウザが起動されて、作ったGASプロジェクトのエディタ画面が開きます。`bot.gs`が作られていることが確認できます。（.jsファイルは.gsファイルとなる）

ウェブエディタから`「公開」->「ウェブアプリケーションとして導入」`を選択します。`更新`ボタンを押すと、追加した権限に対する承認処理が要求されるので、確認して承認します。

承認ができたら一度ローカル環境側でもpullしておきます。

```
$ clasp pull
```

これで一旦GASプロジェクトに関する設定は完了です。

### githubリポジトリの作成
編集対象のgithubリポジトリを作成します。github上で適当な名前のリポジトリを作成してリポジトリURLをコピーしておいてください。

続いて、ローカルのGASプロジェクトをgitに紐付けます。

```
$ git init
$ git remote add origin <リポジトリURL>
```

コミット＆プッシュの前にcircleCIの設定に入ります。

### circleCIのプロジェクト作成

circleCIとは：流行りだしている（?）CI(continuous integration:継続的インテグレーション)サービス。Jenkinsとかが有名（?）ですね。あんまり自分では触れてこなかったので、その勉強も兼ねてます。


まずは、[circleCI](https://circleci.com/)にアクセスしてgithubアカウントでログインします。`「ADD PROJECTS」`から前節で作ったgithubリポジトリを選んで`「Set Up Project」`を押します。

Next Stepsに書かれている通りですが、circleciのコンフィグファイルを作ってpushします。

```
$ mkdir .circleci && touch .circleci/config.yml
```

config.ymlは以下のように編集しておきます。

```config.yml
version: 2

jobs:
  build:
    docker:
      - image: circleci/node:8.9.4

    working_directory: /home/circleci/project

    steps:
      - checkout

      - run:
          name: Show system information.
          command: |
            echo "Node $(node -v)"
            echo "Npm $(npm -v)"

      - run:
          name: deploy to gas
          command: |
            echo $CLASPRC_JSON > ~/.clasprc.json
            echo $CLASP_JSON > ./.clasp.json
            echo 'var ACCESS_TOKEN = "'$LINE_ACCESS_TOKEN'";' > ./config.js
            npx @google/clasp push
            npx @google/clasp deploy -i $DEPLOY_ID
```

gitignoreファイルを作って必要なファイルをまとめてpush

```
$ touch .gitignore
$ echo '.clasp.json' >> .gitignore
$ git add .
$ git commit -m "first commit"
$ git push origin master 
```

pushが完了したら、circleCIのページからstart buildingします。

が、この時点ではbuildが失敗するはずです。`config.yml`内で使用している環境変数の設定が行われていないためです。ちなみに、`Show system information.`までは成功するはずなので、nodeとnpmのバージョンが表示されていることを確認してください。

### circleCI環境変数の設定
GASへのdeployの際に利用している4つの環境変数(`$CLASPRC_JSON`,`$CLASP_JSON`,`$DEPLOY_ID`,`$LINE_ACCESS_TOKEN`)を設定していきます。circleCI上での環境変数の設定は、リポジトリ名の横にある設定ボタン->`「Environment Variables」`から設定することができます。

##### $CLASPRC_JSON:
`clasp login`をすると生成される設定ファイルです。認証トークン情報とかが記載されています。内容をコピーして環境変数に設定してください。

```
$ cat ~/.clasprc.json | pbcopy
```

##### $CLASP_JSON:
`clasp create`するとプロジェクトのディレクトリ内に生成されます。GASプロジェクトのscriptIDが記載されています。これはGASプロジェクトのURLからも取得することが可能です。（`https://script.google.com/d/xxxx/editのxxxxの部分`）内容をコピーして環境変数に設定してください。

```
$ cat ./.clasp.json | pbcopy
```

##### $DEPLOY_ID:
対象のGAS プロジェクトで、すでにウェブアプリケーションとして導入しているバージョンのdeploy_idを取得します。deploy一覧は`clasp deployments`で取得できます。ウェブアプリケーションとして公開されているものは`web app meta-version`という説明が付与されていますので、そのdeploy_idをコピーして環境変数として設定します。circleCIではこのdeployを対象にアップデートしていくことになります。

```
$ clasp deployments
2 Deployments.
- xxxx @HEAD 
- yyyy @1 - web app meta-version <- yyyyの部分をコピー
```

１行で取得するなら以下のような感じに。

```
$ clasp deployments | grep 'web app meta-version' | awk '{print $2}' | pbcopy
```

##### $LINE_ACCESS_TOKEN
名前から想像するとおり、LINEbotがLINEにアクセスするためのトークンです。後述するLinebotの設定を行って取得したアクセストークンを環境変数に設定してください。
このトークンは別にcircleCIの環境変数で管理しなくてもいいのですが、リポジトリにトークン情報いれるのも嫌なのでこちらで設定しています。

### Linebotの設定

ただ、Linebotの設定はいろんな人が画像付きで解説しているので細かな説明はそちらに譲ります。（なげやり）例えば[こちら](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)とか。

必要になるのは

* アクセストークンの取得
* Webhook URLの設定

です。

アクセストークンはLINEbot設定画面の以下赤枠の部分から取得できるので、コピーして、circleCIの環境変数に設定してください。

<img width="1036" alt="スクリーンショット 2019-02-12 11.18.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/19359/c6da0f94-63db-26e2-4cd3-7ff59e21bd8c.png">


Webhook URLは`「公開」->「ウェブアプリケーションとして導入」`から、画像の赤枠部分で確認できます。

<img width="670" alt="スクリーンショット 2019-02-12 11.15.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/19359/c73a6203-6101-784e-0082-8d37ecc2ba9d.png">

こちらをコピーしてLinebotの`Webhook URL`に設定してください。（貼り付けるのは`script.google~`）
※`Webhook送信`を`利用する`に設定するのを忘れずに。

### Linebotプログラミング

さて、あとはbotプログラムを作っていくわけですが、動作確認がてら、おうむ返しするLinebotをつくってみましょう。

ローカル開発環境で以下のようにbot.jsを編集し、`git add & commit & push`してみてください。

```bot.js
var lineEndpoint = "https://api.line.me/v2/bot/message/reply";
function doPost(e) {
  var json = JSON.parse(e.postData.contents);
  var replyToken = json.events[0].replyToken;
  var userMessage = json.events[0].message.text;

  UrlFetchApp.fetch(lineEndpoint, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{
        'type': 'text',
        'text': 'samplebot ver1.00:'+userMessage,
      }],
    }),
  });
}
```
きちんと設定できていれば、`git push`されるとcircleCIのデプロイスクリプトが起動し、claspを使用したコードpushとデプロイが行われるはずです。
line上でbotを友達登録してメッセージを送ると`samplebot ver1.00:`という文字列とともに送ったメッセージが返されるかと思います。

## スマホでプログラミング
ここまでできたらあとはスマホでプログラミングしていくことが可能です。
スマホからgithubのリポジトリページにアクセスして、`PC版サイト`で表示するとソースコードの編集を行うことができます。編集を終えてコミットすると、circleCIによって自動的にデプロイされます。

## 短縮版

以上で作成したプロジェクトもろもろをまとめたリポジトリを作成しました。
https://github.com/naokisekiguchi/gas-linebot-template
適当にForkして使用して頂ければと。
以下に短縮版の手順を記載しておきます。

```
## Fork https://github.com/naokisekiguchi/gas-linebot-template
$ git clone git@github.com:<your account>/gas-linebot-template.git testbot
$ cd testbot
$ npm i @google/clasp -g
$ clasp login
## ログイン処理
$ clasp create
$ clasp push
$ clasp open
## ウェブアプリケーションとして導入->承認処理
$ clasp pull
## circleCIでプロジェクト作成
## Linebotの設定
## circleCIの環境変数の設定
$ cat ~/.clasprc.json | pbcopy
$ cat ./.clasp.json | pbcopy
$ clasp deployments | grep 'web app meta-version' | awk '{print $2}' | pbcopy
## コーディング
$ git add
$ git commit 
$ git push
## botの動作確認
## done!
```

## まとめ

Line botでも作ろうと思ったことでCIサービスとかGASとかclaspとか触れて満足しました。
GASはclaspができたことで（おそらく）格段に開発しやすくなって(git管理が楽になるので)、webサービスとスプレッドシート操作が簡単なので簡易的なツール作成には重宝しそうです。
circleCI簡単に使えそうなので今後活用していきたい。
（本来作ろうと思ってたbotは中途半端で放置されているわけですが）

## 参考

* [Google Apps ScriptでLINE BOTつくったら30分で動かせた件](https://qiita.com/hakshu/items/55c2584cf82718f47464)
* [GAS のGoogle謹製CLIツール clasp](https://qiita.com/HeRo/items/4e65dcc82783b2766c03)
* [Google Apps Script のデプロイを Circle CI から行う](https://qiita.com/howdy39/items/2c21251331e011d04512)
* [1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)