[30分で試す] MS製 BotFrameworkをlocal環境＆Macで使ってみる

# [30分で試す] MS製 BotFrameworkをlocal環境＆Macで使ってみる
ググるとWindows環境での記事は結構あるんだけど、
Mac環境での記事が見つからなかったので自分の整理のためにもまとめてみる
もちろんサーバー不要で、ローカルだけで完結します

# localでの開発環境準備
これらが必須
* コンソール版エミュレータ [Download Console Emulator Zip](http://aka.ms/bfemulator)
* Mono (上のエミュレータを動かすために必要) [Download Mono](http://www.mono-project.com/download/#download-mac)
* [Node](https://nodejs.org/en/)

## エミュレータのインストール
> 公式Docは[こちら](http://docs.botframework.com/connector/tools/bot-framework-emulator/#mac-and-linux-support-using-command-line-emulator)

まずは、エミュレータとMonoをダウンロードする
* コンソール版エミュレータ [Download Console Emulator Zip](http://aka.ms/bfemulator)
* Mono (上のエミュレータを動かすために必要) [Download Mono](http://www.mono-project.com/download/#download-mac)

ここでは、 ``~/BFEmulator`` にエミュレータがおいてあるとして進めます。
Monoのインストールがおわってると下記でエミュレータを起動できる
なお ``BFEmulator.exe`` っていうのは、 ``Bot Framework Emulator`` の頭文字だと、おもわれますw

* こうなってればOK!

```
$ cd ~/
$ mono BFEmulator.exe
Microsoft Framework Emulator

/exit or /quit to exit
/settings to change endpoint, appId and appSecret settings
/dump [#] to show contents of last # messages (default: 1)
/attachment [path] <- to add a file to your message
Current settings:
Endpoint: http://localhost:3978/api/messages
AppId: YourAppId
AppSecret: YourAppSecret

>
```

* なお、ここで何も入れずにEnterうつと、今の状態ではエラーがでる  
これは、Endpoint、AppId、AppSecretが未設定だからだ。

```
Current settings:
Endpoint: http://localhost:3978/api/messages
AppId: YourAppId
AppSecret: YourAppSecret

>
BFEmulator.exe Information: 0 : System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: Error: ConnectFailure (Connection refused) ---> System.Net.Sockets.SocketException: Connection refused
  at System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP) <0x2f374f8 + 0x0017b> in <filename unknown>:0
  at System.Net.WebConnection.Connect (System.Net.HttpWebRequest request) <0x2f36890 + 0x00473> in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetRequestStream (IAsyncResult asyncResult) <0x2f385c8 + 0x000fb> in <filename unknown>:0
  at System.Net.HttpWebRequest.EndGetRequestStream (IAsyncResult asyncResult, System.Net.TransportContext& transportContext) <0x2f385a0 + 0x00020> in <filename unknown>:0
  at (wrapper remoting-invoke-with-check) System.Net.HttpWebRequest:EndGetRequestStream (System.IAsyncResult,System.Net.TransportContext&)
  at System.Net.Http.HttpClientHandler.GetRequestStreamCallback (IAsyncResult ar) <0x2f38278 + 0x00103> in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <0x18aa2b0 + 0x00035> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) <0x18a7ad0 + 0x000b7> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) <0x18a7a30 + 0x00087> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) <0x18a79e0 + 0x0003f> in <filename unknown>:0
  at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () <0x18a82e0 + 0x00024> in <filename unknown>:0
  at Microsoft.Bot.Connector.Emulator.ConversationModel+<SendMessageAsync>d__46.MoveNext () <0x2e597f0 + 0x0097b> in <filename unknown>:0
An error occurred while sending the request.
```

* /exitとうってエミュレータを終了させておく。そもそも、botのサーバーが動いてないから、エラーが出るのは当然。

# 簡単なBotアプリを作ってみる
* エミュレータを使うにしても、ローカルで動くBotアプリがないと話が進まないので、作ってみる

## MSで下準備
* MSのアカウントが必要なので、事前に作っておくこと
* [https://dev.botframework.com/bots/new](https://dev.botframework.com/bots/new) で、サンプルBotのアカウントをつくる
* "Endpoint"の欄には、 `` http://localhost:3978/api/messages `` をダミーで入れておく
* その他のURL (privacyとか)も、この段階では適当に入れておいてOK
* 実際には、自前のhttpsが通るサーバーの準備が必要
* 今回は、ローカルの開発環境についての記事なので、本番向けは他の記事をみてね

## エミュレータの設定を行う
* ``/settings `` コマンドで対話式に設定変更ができる
* AppIdと、AppSecretを更新する
* 上記は、ここで見れるはず[https://dev.botframework.com/bots](https://dev.botframework.com/bots)

```
$ mono BFEmulator.exe
Microsoft Framework Emulator

/exit or /quit to exit
/settings to change endpoint, appId and appSecret settings
/dump [#] to show contents of last # messages (default: 1)
/attachment [path] <- to add a file to your message
Current settings:
Endpoint: http://localhost:3978/api/messages
AppId: YourAppId
AppSecret: YourAppSecret

> /settings
Current Endpoint is: http://localhost:3978/api/messages
Enter to keep it, or type new url.

Current AppId is: YourAppId
Enter to keep it or type a new AppId
<自分のAppId>
Current AppSecret is: YourAppSecret
Enter to keep it or type a new AppSecret
<自分のAppSecret>

>

```

## 簡単なChat-Botをつくる
名前をたずね、それを覚えるだけのchat-botをつくります
事前にNodeをインストールしておいてください。4系でも6系でも動きます
[https://nodejs.org/en/](https://nodejs.org/en/)

### 適当な場所 `` ~/bot-sample`` を作り、そこに移動(cd)する

```
$ mkdir ~/bot-sample && cd ~/bot-sample
$ npm init
  < 聞かれる質問は、全て何も入力せず Enter で進む >

$ npm install --save botbuilder
$ npm install --save restify

おわると↓こうなる
$ ls
node_modules	package.json

```

### app.jsをつくる
下のコードをコピペで、app.jsとして ``~/bot-sample ``配下に保存する
YourAppIdとYourAppSecretは適宜、自分のものに変えること

```app.js
var restify = require('restify');
var builder = require('botbuilder');

// Create bot and add dialogs
var bot = new builder.BotConnectorBot({ appId: 'YourAppId', appSecret: 'YourAppSecret' });

bot.add('/', function (session) {
    if (!session.userData.name) {
        session.beginDialog('/profile');
    } else {
        session.send('Hello %s!', session.userData.name);
    }
});
bot.add('/profile', [
    function (session) {
        builder.Prompts.text(session, 'Hi! What is your name?');
    },
    function (session, results) {
        session.userData.name = results.response;
        session.endDialog();
    }
]);


// Setup Restify Server
var server = restify.createServer();
server.post('/api/messages', bot.verifyBotFramework(), bot.listen());
server.listen(process.env.port || 3978, function () {
    console.log('%s listening to %s', server.name, server.url);
});
```

### Botを起動する

```
$ node app.js
restify listening to http://[::]:3978
```

これでエミュレータからつなぐ用意ができた

# "やっと" エミュレータをつかってみる
別のターミナルを開いて、エミュレータを起動する

```
$ mono BFEmulator.exe
Microsoft Framework Emulator

/exit or /quit to exit
/settings to change endpoint, appId and appSecret settings
/dump [#] to show contents of last # messages (default: 1)
/attachment [path] <- to add a file to your message
Current settings:
Endpoint: http://localhost:3978/api/messages
AppId: <AppId>
AppSecret: <AppSecret>


> <何もせずEnter>
Hi! What is your name?

> Shin
Hello Shin!

```

**うごきました！！**

# まとめ
私はGoogle Cloud Platformでインスタンスを立ててサーバを運用しているのですが、
Botの開発は、実機テストがやりずらくて困ってました。これは簡単でいいですね！
Hubotベースで作ってローカルで動かして、本番デプロイってやってますがDebugがしんどいので困ってました。

MSのフレームワークはこれから更に充実していくはず＆自然言語処理とか機械学習も簡単によべるみたいなので、Hubotからこっちに乗り換えて開発すすめようかなーとおもってます。
これからBot関連の記事を増やしていこうと思うので、興味ある方は[フォローお願いしますー](http://qiita.com/bekoboko)。