MS Teams 用 bot を node.js と heroku で作る方法

# この記事でやること

* Microsoft Teams 用の bot を開発して、bot と会話するところまでを解説します
* コーディングの説明はほぼしません。代わりに、環境やデプロイ方法を中心に説明します
* 宗教上の理由で、Azure や Visual Studio の機能は利用しません

# Bot Framework について学ぶ

現状、Teams 用 bot を開発するには Bot Framework を利用する必要があるため、まずは Bot Framework の概要を理解しておきましょう。

* 参考リンク： [Bot Framework  概要と好きなところ - SecretaryBot 開発チーム Blog](https://secretarybotja.wordpress.com/2017/02/12/bot-framework-%e6%a6%82%e8%a6%81%e3%81%a8%e5%a5%bd%e3%81%8d%e3%81%aa%e3%81%a8%e3%81%93%e3%82%8d/)
    * ざっくりまとめ 
        * MSが、Bot Connector や State Service という bot 開発に便利なクラウドサービスを提供している
        * 自分は、Bot Builder SDK を使って、それらのクラウドサービスと連係した bot 用 Web アプリを作ればよい
    * 補足事項
        * 自分で開発した bot 用 Web アプリに、Bot Connector から https 通信できる必要がある（グローバルに足を出す必要がある）
        * bot を動かすには Developer Portal への登録が必要だが、Bot Directory に登録しない限り一覧には載らない
            * 載らないだけで、後述の Microsoft App ID さえわかれば誰でも bot と会話できてしまうので注意
            * bot アプリ側で、誰が話しかけてきているかを見て制御するしかない？

# Bot を登録する

コードを書いてデプロイする前に bot の ID が必要なので、先に登録します。

1. https://dev.botframework.com/ からログイン
    * Teams を使いたい組織のアカウントでログインすること
1. `My bots` から bot を登録
    * 入力項目は一旦全て適当で OK だが、`Bot handle` だけはあとで変えられないのでよく考えて決める
    * `Create Microsoft App ID and password` をクリックして ID とパスワードを発行しておく
        * 以後、この ID がこの Bot を表すようになる
1. 登録が完了すると Connect to channels ページに飛ぶので、`Add a channel` から Teams を追加

# コードを書いて Heroku にデプロイする

## 最小限のコード
* https://github.com/megane42/botbuilder-sample/
* コードに Teams など具体的なチャットツール名が出てこないことに注目（＝ 複数のチャットとの連携が容易）

## デプロイ
* [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/megane42/botbuilder-sample)
    * このボタンをクリックすると、上記「最小限のコード」を Heroku にデプロイします
    * さっき取得した Microsoft App ID / PW を入力する

## 接続先の設定
* [My bots](https://dev.botframework.com/bots) から動作確認したい bot を選択
* `SETTINGS` を開き、 `Messaging endpoint` に今デプロイした Heroku の URL + `/api/messages` を記入
    * 例: https://foo-bar-12345.herokuapp.com/api/messages

# bot と 1 vs 1 でチャットする

* [My bots](https://dev.botframework.com/bots) から動作確認したい bot を選択
* Channel 一覧の `Microsoft Teams` をクリックする（下図参照）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/66421/174d2249-0111-edac-f7f0-64cab26a4002.png)

* Teams が起動して、bot と 1vs1 のチャットが始まる
* 何か発言して、bot が「Hello World」と返してくればOK

![image.png](https://qiita-image-store.s3.amazonaws.com/0/66421/8b20a47e-1cd8-5b00-b5ef-7ea1777f32f5.png)

## 別の方法

![image.png](https://qiita-image-store.s3.amazonaws.com/0/66421/6b327828-808b-7ea2-d9ef-85b76687296c.png)

* 新規チャットを開始（下図　左の丸で囲ったボタン）
* メンバーに bot の Microsoft App ID を入力すると、bot との 1 vs 1 チャットが始まる
    * ID さえわかれば誰でも bot と会話できてしまう！

# bot とチーム内でグループチャットする

上記の手順では、bot との 1vs1 のチャットしかできませんでした。ChatOps 的なことがしたい場合、チームメンバーとのグループチャットの中で bot と会話する必要があるかと思うので、そのようにします。

このプロセスがなぜか煩雑でした。具体的には、packaging したあと sideloading するという手順を踏みます。

## packaging

* https://msdn.microsoft.com/en-us/microsoft-teams/createpackage
* packaging == XML とアイコンを zip で固めること
* 上記ページから [サンプル](https://github.com/OfficeDev/Microsoft-teams-docs/blob/master/teams/SimpleBotPackage.zip) がダウンロードできる
    * XML の必須項目が多くて大変だが、外部に公開する予定がないなら `id` と `bots > botId` だけ書き換えればとりあえず動く
        * さっき取得した MS App ID を書く
        * 他の項目は bot 追加時の表示などに使われている
    * 余力があればアイコンくらい作っておくとテンションが上がる & bot 一覧での管理がラク

## sideloading

* https://msdn.microsoft.com/en-us/microsoft-teams/sideload

> サイドローディングとは、アプリケーションストアを通じてアプリの配布や管理を行っているシステムにおいて、正規のアプリケーションストアを経由せずにアプリを入手し、インストールすることである。
> http://www.weblio.jp/content/sideload

* 追加したいチームの「…」 → チームを表示 → ボットタブ → ボットまたはタブをサイドロード
    * 管理者の設定によっては「ボットまたはタブをサイドロード」が表示されないので注意
        * https://blogs.msdn.microsoft.com/lync_support_team_blog_japan/2016/11/25/start-microsoft-teams-2/
* さっき作った zip をアップロードすると、bot がチームに参加する

## 動作確認

* 追加したチームのチャットで bot にメンションを送り、「Hello World」と返信があれば OK

![image.png](https://qiita-image-store.s3.amazonaws.com/0/66421/0e33062d-065c-b6dc-f928-eae4c4a2e1ca.png)

# まとめ

* MS Teams 向け bot を作るには、Bot Framework を利用して Web アプリを開発すればよい
    * Azure や Visual Studio の利用は必須ではない
* bot 用 Web アプリはグローバルに公開する必要がある
* Microsoft App ID さえ知られれば誰でも bot を使えてしまう
* 1 vs 1 の対話は比較的簡単に始められるが、グループチャットするためには packaging と sideloading が必要
    * packaging 時に書く XML は、プライベートな用途なら ID 以外適当で大丈夫
    * sideloading は管理者の設定によっては実行できないので、許可してもらう

# おまけ：Bot Framework Emulator を使う

Bot Framework Emulator (https://github.com/Microsoft/BotFramework-Emulator) を使うことで、わざわざデプロイしなくてもローカルで動作確認が可能です。以下、その方法をまとめます。

1. `git clone https://github.com/megane42/botbuilder-sample.git`
2. `cd botbuilder-sample`
3. `npm install`
4. `npm start`
5. Bot Framework Emulator をダウンロード (https://emulator.botframework.com/)
6. エミュレーターを起動し、アドレスバーに http://127.0.0.1:3978/api/messages と入力して CONNECT をクリック（下図）
7. なにか発言して「Hello World」と返ってくれば OK

![image.png](https://qiita-image-store.s3.amazonaws.com/0/66421/550aa2eb-840b-0b7d-d7d3-a2844b216128.png)

ポイントは、

* ローカルで .env ファイルを用意しない（ID/PW を空にしておく）
* エミュレーターのアドレスバーに入力する URL を https ではなく http にして、ID/PW は入力しない

ことです。今回の bot アプリのコードだと https 通信を扱えず、ID/PW を使った通信ができないためです。
また、開発環境がプロキシ配下の場合は、環境変数 `HTTP_PROXY` `HTTPS_PROXY` を設定しておく必要があるかもしれません。