LINE の Bot 開発 超入門（前編） ゼロから応答ができるまで C# 編

LINE の Bot 開発 超入門（前編） ゼロから応答ができるまで C# 編
※Node.js 編は[こちら](https://qiita.com/nkjm/items/38808bbc97d6927837cd)

# 概要

この記事では LINE で動作する Bot を開発する方法をチュートリアル形式で記載しています。カバーする内容は、「寿司の出前を受付する Bot」を開発するというもので、LINE 側での必要な設定、Bot 本体の開発とクラウド環境へのデプロイ、そして自然言語解析を組み込んでユーザーの意図を特定する機能など Bot に共通して求められる基本的な動作を含みます。今回の Bot 本体は C# と ASP.NET Core で作っていきます。

# 必要なスキルと環境

- C# と ASP.NET Core の基本的な知識
- [Visual Studio Code](https://code.visualstudio.com/) の基本的な操作方法
- dotnet core SDK [Windows](https://www.microsoft.com/net/learn/get-started/windows)/[Linux](https://www.microsoft.com/net/learn/get-started/linuxredhat)/[Mac](https://www.microsoft.com/net/learn/get-started/macos)
- [Azure サブスクリプション](https://azure.microsoft.com/ja-jp/free/)
- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) 
- [Node.js](https://nodejs.org/ja/download/): ソリューションテンプレートとシミュレーター用
- [git](https://git-scm.com/download)

# 開発の流れ

- まず最初に LINE Bot のアカウントを作成します。この作業は LINE Developers コンソールという Web サイトで「Channel」を作成するという作業になります。 *＊以後 Bot のアカウントのことを Channel と呼びます。*
- 次に Bot 本体のプログラムを開発し、クラウド上の実行環境へデプロイします。これで Bot 自体は稼働している状態になります。
- そして Bot の Channel の設定で Webhook を設定し、Bot に送信されたメッセージなどを含むイベントが Bot のインスタンスに転送されるようにします。
- 残りの開発はシミュレーターを利用したローカル環境で行います。
- 最後に完成した Bot 本体のプログラムをクラウドにデプロイします。

# 手順

## Channel を作成する

1\. [LINE Developer コンソール](https://developers.line.me/ja/)にアクセスし、ログインボタンをクリックして自身の LINE アカウントでログインします。
![login.png](https://qiita-image-store.s3.amazonaws.com/0/26079/869f72dd-d485-d8eb-ec6c-08fc6d60a438.png "login.png")

2\. はじめてログインしたときには開発者登録を求められますので必要事項を入力してください。
![first login.png](https://qiita-image-store.s3.amazonaws.com/0/26079/b78f6caf-7302-c573-8662-8589b58b94c6.png "first login.png")

3\. 「はじめる」をクリックして次のスクリーンに移ります。
![get_started.png](https://qiita-image-store.s3.amazonaws.com/0/26079/a1d7bb5e-77c6-2e93-fc8e-25eff50d136c.png "get_started.png")

4\. 次にプロバイダーを作成します。プロバイダーとはこれから作成する Bot の提供元として表示される情報です。
![welcome_to_console.png](https://qiita-image-store.s3.amazonaws.com/0/26079/a6a3aafd-552c-8ba1-f4c0-078334943741.png "welcome_to_console.png")

5\. 必要情報を入力して進んでください。
![new provider.png](https://qiita-image-store.s3.amazonaws.com/0/26079/17c03b9d-954c-1c1c-df87-9f1482dac914.png "new provider.png")

6\. 次に Channel を作成します。Channel には LINE ログインと Messaging API の 2 つが存在します。今回作成するのは Bot なので Messaging API を選択してください。
![new_provider_created.png](https://qiita-image-store.s3.amazonaws.com/0/26079/504bc7c7-0df7-fe92-59a5-5316ca8861ec.png "new_provider_created.png")

7\. こちらの画面で必要情報を入力していきます。
![new channel.png](https://qiita-image-store.s3.amazonaws.com/0/26079/338e030a-06db-e4d8-2a1d-22d973e4b4d5.png "new channel.png")
    - アプリ名: **任意のアプリ名**
    - アプリ説明: **任意のアプリ説明**
    - プラン: **Developer Trial**
    - 大業種: **飲食店・レストラン**
    - 小業種: **すし**
    - メールアドレス: **ご自身のメールアドレス**
        
8\. これで Channel が作成されますが、まだもう少し設定が必要です。「設定が完了していません」をクリックします。
![configure_channel.png](https://qiita-image-store.s3.amazonaws.com/0/26079/80683ebd-d650-d544-f7c9-df09fc903299.png "configure_channel.png")

9\. メッセージ送受信設定のセクションにあるアクセストークンの「再発行」ボタンをクリックします。
![issue_channel_access_token.png](https://qiita-image-store.s3.amazonaws.com/0/26079/b848603d-e7f2-a5e3-606a-214ba70420c9.png "issue_channel_access_token.png")

10\. 失効までの時間を 0 時間にしてそのまま再発行をクリックします。0 時間にすることでトークンが失効しません。
![reissue.png](https://qiita-image-store.s3.amazonaws.com/0/26079/a191fb50-4ba1-82e5-42d7-f690a6aea67e.png "reissue.png")

11\. これでアクセストークンが発行されます。このトークンは Messaging API の呼び出し時に認証情報として必要になります。あと残りの項目を下記の通り設定します。

**メッセージ送受信設定**

- Webhook 送信: **利用する**

**LINE@ 機能の利用**

- 自動応答メッセージ: **利用しない**
- 友達追加時あいさつ: **利用しない**

これで Channel の設定は**ほぼ**完了です。Bot 本体をクラウドにデプロイしてからWebhook URL の設定を後ほどおこないます。
また、Bot 本体の開発で Channel Secret とアクセストークンが必要になりますのでこのページは開いたまま、次のステッップへ進みます。

## ソリューションテンプレートとシミュレーターのダウンロード
yeoman を使ったソリューションテンプレートと LINE Bot シミュレーターを npm に公開してます。以下の手順で必要な npm パッケージを取得します。

Windows の場合

```
npm install -g yo
npm install -g generator-line-bot
npm install -g line-simulator
```
Mac の場合

```
sudo npm install -g yo
sudo npm install -g generator-line-bot
sudo npm install -g line-simulator
```
## Azure 環境の準備

Azure ポータルを使い慣れている場合はポータルからの操作でもいいですが、今回は Azure CLI を使って見ます。

1\. まだインストールしていない場合は、[Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) をインストールします。

2\. 以下のコマンドでログインを実行します。

```
az login
```

3\. 画面の指示に順ってログインを完了します。

4\. ログイン完了後、複数の Azure サブスクリプションがある場合は、以下のコマンドで使うサブスクリプションをセットします。

```
az account list
az account set -s 'subscription id'
az account show
```
5\. まず以下のコマンドでリソースグループを linebotsample の名前、地域を東日本で作成します。

```
az group create -n linebotsample -l japaneast
```

6\. 次にストレージアカウントを作成します。名前はグローバルで一意になるようにしてください。以下では linebotstorage の名前作成しています。このストレージにはボットのステータスを保存します。

```
az storage account create -n linebotstorage -g linebotsample --sku Standard_LRS
```

7\. 作成したストレージに接続するための接続文字列を取得します。結果を保存しておいてください。

```
az storage account show-connection-string -n linebotstorage -g linebotsample
```

8\. 次に開発したボットのデプロイ先となる WebApps を作成します。WebApp 作成時には、まずサービスプランを作成し、WebApp を作成します。また名前は一意になるようにしてください。

```
az appservice plan create -n linebotappplan -g linebotsample --sku F1
az webapp create -n kenakamulinebot -g linebotsample -p linebotappplan
```

9\. その後 git デプロイの指定をします。戻り値がデプロイ先となるので保存しておいてください。ユーザー名とパスワードは適宜変更します。パスワードはデブロイ時に必要です。尚、このユーザーはサブスクリプション内のアプリで共通となるので、これまでに設定したことがある場合は、1 つ目のコマンドはスキップしてください。

```
az webapp deployment user set --user-name kenakamu --password Pa$$w0rd
az webapp deployment source config-local-git -n kenakamulinebot -g linebotsample
```

## Bot本体（C# のプログラム）を開発する

準備が整ったところで、ボットを開発していきます。

1\. コマンドプロンプトやターミナルでデスクトップ等任意の場所に移動します。

2\. 以下のコマンドで C# WebAPI 用のテンプレートを展開します。実行時に LINE ボットのチャネルシークレット、チャネルトークン、また Azure ストレージアカウントの接続文字列を聞かれるので、それぞれ入力します。

```
yo line-bot sushibot --csharp --webapi
```

3\. 作成されたフォルダに移動します。

```
cd sushibot
```

## Bot本体を Azure WebApp に展開する

1\. 今回は git で展開するため、まずレポジトリを初期化します。

```
git init
```

2\. 次に発行先を設定します。アドレスは WebApp 作成時に取得したものを使います。

```
git remote add origin https://kenakamu@kenakamulinebot.scm.azurewebsites.net/kenakamulinebot.git
```

3\. Visual Studio Code を開きます。

```
code . --locale=ja
```

4\. 新規ファイルより、ルートに .gitignoreファイルを作成し、git の管理対象外にしたいファイルを一行一ファイルで列挙します。

```text:.gitignore
.vscode
bin
debug
```

5\. ターミナルまたはコマンドプロンプトに戻り、以下コマンドでコミットを行います。

```
git add .
git commit -m "初回コミット"
```

6\. 以下のコマンドでデプロイします。パスワードを聞かれるので、設定したものを入力します。初回は少し時間がかかります。

```
git push -u origin master
``` 

## Webhookを設定する

Webhook は LINE で Bot に関連するイベントが発生した場合に、そのイベントを Bot インスタンスに通知してもらうためのアクセスポイント（URL）です。

この URL は開発者が指定することができ、その URL に対して LINE から POST リクエストが送信されることになります。今回は下記の URLを Webhook として設定します。

https://自分のwebapp名.azurewebsites.net/api/linebot

LINE Developers コンソールでWebhook URLを下記の通り設定します。

```
https://自分のwebapp名.azurewebsites.net/api/linebot
```

ここで Bot を友達に追加しておきましょう。スマホで LINE を起動し、LINE Developers コンソールのチャネルにある QR コードをスキャンして追加します。iOS 版の場合は下記のような手順になります。

![IMG_0027.png](https://qiita-image-store.s3.amazonaws.com/0/26079/2b0d3c7f-e9ec-e47f-add4-e1ffb0e39692.png "IMG_0027.png") ![IMG_0028.png](https://qiita-image-store.s3.amazonaws.com/0/26079/049844ef-7271-251f-e91a-1a98fa6f09b8.png "IMG_0028.png")

任意のメッセージを送ってみてください。返信があれば無事に繋がっています。

## Kudu
デプロイ済みのサーバー情報は、Kudu というツールで確認ができます。

1\. デプロイ先 git アドレスのホスト URL にブラウザでアクセスします。トップページに環境の概要があります。
例) https://kenakamulinebot.scm.azurewebsites.net

2\. 上部メニューより Debug console をクリックし、CMD または PowerShell を選択します。 

3\. site -> wwwroot 内に展開済みファイルが確認できます。また LogFiles 配下にはさまざまなログがあります。詳しく紹介しているので

Kudu については[こちらのブログ](https://buchizo.wordpress.com/2013/12/22/windows-azure-web-sites%E3%81%AE%E9%AD%85%E5%8A%9B%E3%82%92120%E5%BC%95%E3%81%8D%E5%87%BA%E3%81%99/) で詳細が紹介されているので是非ご覧ください。

## メッセージの返信

それでは、ユーザーが Bot に「こんにちは」とテキストメッセージを送ってきたら「これはこれは」と返信するようにしてみます。

1\. Visual Studio Code で LineBotApp.cs を開きます。このテンプレートは様々なサンプルを含んでいるため、いかのコードと差し替えてシンプルにします。ユーザーから送られてきたテキストは HandleTextAsync メソッドで返信を作って返しています。

```c#:LineBotApp.cs 
using Line.Messaging;
using Line.Messaging.Webhooks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using sushibot.CloudStorage;
using sushibot.Models;

namespace sushibot
{
    internal class LineBotApp : WebhookApplication
    {
        private LineMessagingClient messagingClient { get; }
        private TableStorage<EventSourceState> sourceState { get; }
        private BlobStorage blobStorage { get; }

        public LineBotApp(LineMessagingClient lineMessagingClient, TableStorage<EventSourceState> tableStorage, BlobStorage blobStorage)
        {
            this.messagingClient = lineMessagingClient;
            this.sourceState = tableStorage;
            this.blobStorage = blobStorage;
        }

        protected override async Task OnMessageAsync(MessageEvent ev)
        {
            switch (ev.Message.Type)
            {
                case EventMessageType.Text:
                    await HandleTextAsync(ev.ReplyToken, ((TextEventMessage)ev.Message).Text, ev.Source.UserId);
                    break;
            }
        }

        private async Task HandleTextAsync(string replyToken, string userMessage, string userId)
        {  
            var replyMessage = new TextMessage($"You said: {userMessage}");
            if(userMessage == "こんにちは"){
               replyMessage.Text = "これはこれは"; 
            }

            await messagingClient.ReplyMessageAsync(replyToken, new List<ISendMessage> { replyMessage });
        }
    }
}
```

2\. 再度以下のコマンドでデプロイします。

```
git commit -am update
git push
```

3\. 再度ボットに話しかけます。うまくいけば「こんにちは」に対して、「これはこれは」と返しますが、他の言葉はおうむ返しをするだけです。

# シミュレーターを使ったデバッグ
デプロイ済みの環境をデバッグするのは多少の困難を伴うため、以下にシミュレーターを使ってデバッグできるよう設定します。

1\. Controllers フォルダにある、LineBotController.cs を開き、コンストラクターを以下の変更します。

```c#:LineBotController.cs 
public LineBotController(IOptions<AppSettings> options)
{
    appsettings = options.Value;
    #if DEBUG
    lineMessagingClient = new LineMessagingClient(appsettings.LineSettings.ChannelAccessToken,
        "http://localhost:8080");
    #else
    lineMessagingClient = new LineMessagingClient(appsettings.LineSettings.ChannelAccessToken);
    #endif
}
```
2\. F5 を押下して、デバッグを開始します。ブラウザが開くのでアドレスを確認します。アプリケーションは /api/bot に対する HttpRequest のみハンドルするため F5 押下で表示されるブラウザはエラーになりますが、無視してください。※既定で localhost:5000

3\. LineBotApp.cs 39 行目にブレークポイントをおきます。<br>![Screen Shot 2018-01-20 at 12.58.27 AM.png](https://qiita-image-store.s3.amazonaws.com/0/214116/6e5662b3-6d77-73d3-a459-2cb43d88fe38.png)


4\. 新しくコマンドプロンプトやターミナルを開き、以下のコマンドでシミュレーターを起動します。

```
line-simulator
```

5\. ブラウザを開いて、http://localhost:8080 に接続します。

6\. はじめに接続画面が出ます。それぞれ値を入れて CONNECT をクリックします。
    - UserId は LINE Developers コンソールのチャネル一番下に表示されている値を使います。
    - Bot API Server Address http://localhost:5000/api/linebot ※アドレスは上記手順で確認したもの。
<br>
![Screen Shot 2018-01-20 at 12.49.33 AM.png](https://qiita-image-store.s3.amazonaws.com/0/214116/7fd70285-6121-3437-8981-4a1c84a4101f.png)

7\. チャットバーより「こんにちは」と入力します。ブレークポイントがヒットすることを確認します。<br>![Screen Shot 2018-01-20 at 12.59.46 AM.png](https://qiita-image-store.s3.amazonaws.com/0/214116/2c7f50b0-09d3-2d09-57d9-cc44153839a4.png)

8\. F5 を押下してシミュレーターを確認します。<br>![Screen Shot 2018-01-20 at 1.00.52 AM.png](https://qiita-image-store.s3.amazonaws.com/0/214116/6894d88e-5bf5-ce7e-f929-c593a7cc9a59.png)

# 次のステップ

[（後編）メッセージの意図と文脈を意識した会話を実現する](https://qiita.com/kenakamu/items/ac4922a2061f4f8f02d9)