Bot Builder v4 でボット開発 : 最小限構成でまずはオウム返しボットを作る

この記事では Visual Studio テンプレートやサンプルを使わず、最小限構成で「オウム返しボット」を開発してみます。

BotBuilder v4 は .NET Standard で開発されているため、.NET Framework および dotnet core のいずれでも動作しますが、クロスプラットフォームを意識して、dotnet core/Visual Studio Code (VSCode) で開発していきます。

# 事前準備

[VS Code](https://code.visualstudio.com/Download)
[C# 拡張機能](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp)
[dotnet core 2.1](https://www.microsoft.com/net/download)
[Bot Framework Emulator](https://github.com/Microsoft/BotFramework-Emulator/releases)

# プロジェクトの作成

ボットアプリとは、ただ単に Web API アプリケーションのことです。よって以下手順で Web API プロジェクトを作成します。

1\. 以下コマンドを実行して Web API プロジェクトを作成。VSCode で開く。

```shell
dotnet new webapi -n myfirstbot
code myfirstbot
```

2\. 以下コマンドで開発時に使う証明書を信頼する。

```shell
dotnet dev-certs https --trust
```
3\. MVC Web API としてプロジェクトが作成されるが、標準の MVC 機能とコントローラーは使わないため、Contollers フォルダを削除。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/63893c6c-a4b0-5058-682b-73a342fec6c7.png)

4\. Startup.cs より Configure および ConfigureServices の中身を以下コードに置き換え。MVC 機能を一切使わず、「Hello Bot!」という文字列だけを返す。

```csharp
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{

}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("Hello, Bot!");
    });
}
```
5\. F5 キーを押下してデバッグ実行。ドロップダウンより ".NET Core" を選択。F5 を再度押下してデバッグ開始。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/dbd2be38-4e6e-a39a-e1b0-e03858a183ea.png)

6\. 「Hello Bot」が表示されれば準備完了。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/4a2a8ac5-f0d3-e092-7f6a-2dea32836011.png)

# Bot の追加

次に最低限必要な NuGet パッケージの追加とコードの追加を行います。

1\. 以下コマンドで Microsoft.Bot.Builder.Integration.AspNet.Core NuGet パッケージを追加。

```shell
dotnet add package Microsoft.Bot.Builder.Integration.AspNet.Core
```

2\. ログより依存関係として Bot.Builder 関連のパッケージも追加されていることを確認。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/83f0e44b-9377-8002-67e5-fa5bed65e6a8.png)

3\. プロジェクトに MyBot.cs　ファイルを追加して、IBot インターフェースを継承。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/611b7224-f169-e8bf-c43d-7589eb80a8ca.png)

4\. 赤線が出ているところにカーソルを合わせて 「Ctrl ⁺ . (ドット)」 ショートカットを押下。選択肢より「using Microsoft.Bot.Builder;」を選択。自動的に using ステートメントが追加される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/f7d1daca-085e-c282-61a9-a0f4ddb00027.png)

5\. 再度、赤線が出ているところにカーソルを合わせて「Ctrl ⁺ . (ドット)」 ショートカットを押下。選択肢より「Implement interface」を選択。必要なメソッドが追加される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/1f824871-c985-d3cb-a96c-81f34d12d776.png)

6\. OnTurnAsync が追加されるので、async キーワードを追加。ボットが実行されると、この OnTurnAsync メソッドが実行される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/4962c622-ceb2-fd9f-0738-52eeb8b2755e.png)

7\. 以下のコードを追加。

```csharp
await turnContext.SendActivityAsync("Hello from MyBot");
```

8\. 結果として MyBot.cs は以下の様になる。

```csharp:MyBot.cs
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;

public class MyBot : IBot
{
    public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        await turnContext.SendActivityAsync("Hello from MyBot");
    }
}
```

9\. 次に Start.cs を以下の様に変更。using の追加と ConfigureServices および Configure メソッドに Bot 関連のコードを追加。

```csharp:Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace myfirstbot
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddBot<MyBot>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
           app.UseBotFramework();
        }
    }
}
```

# Bot のテスト

では実際に現時点の動作を確認してみます。

1\. F5 キーを押下して Bot を実行。コンソールより起動したポートを確認。http を使うため、この環境ではポート 5000。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/6e572a0a-9825-14ea-f1b7-5fb95ee893f7.png)

2\. Bot Framework Emulator を起動。「create new bot configuration」をクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/9ce5a7bd-1d5f-e1a8-102c-887c4eaccd1f.png)

3\. 名前に「MyBot」、Endpoint URL に「http\://localhost:5000/api/messages」と入力。ポートは環境に合わせて変更するが、「/api/messages」を忘れない。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/7e2e7f12-5cd1-49fe-b1db-83b6cf835b4d.png)

4\. 「Save and connect」をクリック。ファイルの保存を聞かれるので、MyFirstBot フォルダに保存。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/4e12ca52-a6fd-f1be-4de7-4cce3d218477.png)

5\. メッセージを打つ前に 2 つ「Hello from MyBot」が返ることを確認。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/4352e1cf-35ef-9ba1-2813-c9a3955cb349.png)

6\. 手動でメッセージを送信。「Hello from MyBot」が返ることを確認。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/abca9b65-a51b-4bb2-ffcc-adeed4fc3a85.png)

7\. デバッグを停止。

# Bot の改修

現在は文字を打つ前に返信があるため、ユーザーのメッセージにだけ反応し、オウム返しをするように改修します。

1\. MyBot.cs を以下のコードと差し替え。

```csharp:MyBot.cs
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
public class MyBot : IBot
{
    public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        // ユーザーのメッセージにだけ返信
        // Text プロパティの値をオウム返し
        if(turnContext.Activity.Type == ActivityTypes.Message
            && !string.IsNullOrEmpty(turnContext.Activity.Text))
            await turnContext.SendActivityAsync(turnContext.Activity.Text);
    }
}
```

2\. F5 を押下して起動。エミュレータで「Start Over」をクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/d36d5855-267f-2115-8d7c-aa885b40d2c1.png)

3\. メッセージを手動で送って返信を確認。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/c1c037ff-a6ef-dfcc-2794-d225d1614c36.png)

# まとめ

今回は、まず最小構成で「オウム返しボット」を開発しました。重要な事は以下の 3 点です。

- ボットは IBot インターフェースを継承する
- OnTurnAsync に実際のコードを書く
- Startup.cs に BotFramework 呼び出しのコードを書く

次回は、今回のコードが実際にどういう仕組みで動作しているのかを見ていきます。

[次の記事へ](https://qiita.com/kenakamu/items/25667b7359bc1f38cf15)
[目次に戻る](https://qiita.com/kenakamu/items/6dc043cfc1f199032883)

[この記事のサンプルコード](https://github.com/kenakamu/botbuilderv4completeguide/tree/article1)