SkypeとチャットAIのGateWayを作ってみた。 

昨今チャットボットが流行っているが、今度はSkypeで・・・という要望を受けた。

AIエンジンは既にRestAPIで持っている。問題はSkypeとAIの仲介役をどう実現するかだ。
手探りであったがどうやら「**[Bot Framework REST APIs](https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-overview)**」なるもので実現できそうだ。

***

ざっくり構成はこんな形だ。
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/ad13e031-08e8-2043-db40-a942618fa923.png)


***

次のような順で解説する。尚、AIは単純なRestAPIなので省く。
（１）GateWay Server 構築
（２）Azure Bot Frameworkの設定

***

（１）GateWay Server 構築
・まずBotFrameworkからのイベント通知はWebhookなので受け取れる口を準備する。
　Https対応必須なのでHAProxyやspring-bootなどで対応する。
　FireWallの口開けも忘れずに。
　今回はJava＋HAProxyで対応した。中身についてはAzureからきた質問をAIにRestリクエスト
　で流す。回答はWebhookで連携されるので、こいつをBotFrameworkにRestリクエストで返すだけだ。実際はAIエンジン用のユーザ管理などやっているが、今回の記事には関係ないことなので省く。

***

（２）Azure Bot Frameworkの設定
・ここが今回のメインになる。
　[Azure Portal](https://portal.azure.com/)から設定する。
　BOTの実現方法にはAzure上にアプリを配置する方法もあるようだが、今回はアプリは別鯖に用意　してWebhookだけかけてもらうこととする。（過去資材を流用したらこうなっただけで、特段お勧めなわけではない。）

　１）BotChannelの作成
選んでいくだけだ。
![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/679a66e9-56ad-2816-9e9e-91e0d90aad15.png)

![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/5b1b063c-64f8-4487-8c69-280eade3a691.png)

![4.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/b5d2d6ee-ef9b-d5c9-5824-0f3172e906ed.png)

Botの名前やサブスクリプション方法、WebhookをかけてもらうエンドポイントURLなどを入力する。
![5.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/9862c421-53db-2673-2cca-9b453fa6efa8.png)

２）Channel設定
作ったBOTを選択
![6.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/0315fd3d-532b-4244-3978-fa39b87ff9c0.png)

![7.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/2f1bd1b9-f863-4ad6-04c6-8cfe510c3073.png)

自前のGateWayServerからBotFrameworkに回答をRestリクエストするには、認証のためのアクセストークンが必要だ。こいつはRestAPIで発行可能だが、そのためにはアプリケーションIDとシークレットキーが必要になる。それを下記の画面で取得しておく。これらは永久に利用できるようだ。（ただし、アクセストークンは時間限定なので期限切れになる前に再発行する仕組みをGateWayServer側に作りこんでおく必要はある。）
![8.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/1965f3ed-8ff3-06bc-b4d0-8ec7a188671d.png)

BOTにデフォルトで紐付けされているチャンネルは、Webページ埋め込みパーツ用のみである。
ここにSkypeチャンネルを追加する。（**正確にはSkypeには無料で利用できる一般消費者向けとSkype for Businessのエンタープライズ向けがある。この記事で扱うのは前者である。**)
![9.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/ca50120b-7626-ac61-af4a-0884a70ba625.png)

![10.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/7cb0268c-b456-62e3-d08d-ee7840c61e5a.png)

作ったチャンネルの動作確認
![11.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/ab55f8ad-d785-a4cd-ca5c-f09e1b7c54af.png)

![12.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/fc2354c3-01a2-8acc-e1b4-3e4cefb97823.png)

Skypeが開くので発話してWebhookが飛んでくれば問題なく動いている。
![13.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/c771caa5-1598-1b8c-3c37-264b3e56593f.png)

***
2018/4/10追記
Skypeに送れるメッセージを抜粋で紹介。詳しくはー＞**[Bot Framework REST APIs](https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-overview)**

※前段階としてACCESS_TOKENを取得しておく必要がある。
　AzureサイトからBOT作成時に取得した
　・アプリケーションID (ApplicationId)
　・アプリケーションシークレット (ApplicationSecret)
　を用いてRestAPIをたたくことで取得できる。有効期限は１時間のもよう。
```haml:Header
POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
```

```json:BODY
grant_type=client_credentials&client_id=<ApplicationId>&client_secret=<ApplicationSecret>&scope=https%3A%2F%2Fapi.botframework.com%2F.default
```

１．URLリンク
　テキストメッセージ中に特殊文として埋め込める。

```haml:Header
POST https://smba.trafficmanager.net/apis/v3/conversations/<conversationId>/activities/<replyTokenId>
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
```

```URLリンク[Google](http://www.google.co.jp/)めっせーじ```

２．ボタン付きテンプレート
　以下のJSONでリクエスト

```haml:Header
POST https://smba.trafficmanager.net/apis/v3/conversations/<conversationId>/activities/<replyTokenId>
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
```

```json:JSON
{
    "type": "message",
    "from": {
        "id": "28:bdbc4595-004c-41a9-af22-1bf2b48ab542",
        "name": "cotohaBotPOC"
    },
    "conversation": {
        "id": "29:1nMbiqCmbifApQ_B6qVcx_ydAvvdO4jlhpLEyJwSvy3w"
    },
    "recipient": {
        "id": "29:1nMbiqCmbifApQ_B6qVcx_ydAvvdO4jlhpLEyJwSvy3w",
        "name": "yuka toyoda"
    },
    "attachments": [
        {
            "contentType": "application/vnd.microsoft.card.hero",
            "content": {
                "title": "title",
                "subtitle": "subtitle",
                "images": [
                    {
                        "url": "画像パス、URL"
                    }
                ],
                "buttons": [
                    {
                        "type": "imBack",
                        "title": "button1",
                        "value": "button1"
                    },
                    {
                        "type": "openUrl",
                        "title": "button1",
                        "value": "任意のURL"
                    }
                ]
            }
        }
    ]
}
```
表示例：
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/c6eef9b6-a1e4-92fc-1447-97ed32fd63bf.png)

３．画像付きボタン（画像小）
　以下のJSONでリクエスト

```haml:Header
POST https://smba.trafficmanager.net/apis/v3/conversations/<conversationId>/activities/<replyTokenId>
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
```

```json:JSON
{
    "type": "message",
    "from": {
        "id": "28:bdbc4595-004c-41a9-af22-1bf2b48ab542",
        "name": "cotohaBotPOC"
    },
    "conversation": {
        "id": "29:1nMbiqCmbifApQ_B6qVcx_ydAvvdO4jlhpLEyJwSvy3w"
    },
    "recipient": {
        "id": "29:1nMbiqCmbifApQ_B6qVcx_ydAvvdO4jlhpLEyJwSvy3w",
        "name": "yuka toyoda"
    },
    "attachments": [
        {
            "contentType": "application/vnd.microsoft.card.thumbnail",
            "content": {
                "title": "title",
                "subtitle": "subtitle",
                "images": [
                    {
                        "url": "画像パス、URL"
                    }
                ],
                "buttons": [
                    {
                        "type": "openUrl",
                        "title": "button1",
                        "value": "任意のURL"
                    },
                    {
                        "type": "openUrl",
                        "title": "button1",
                        "value": "任意のURL"
                    }
                ]
            }
        }
    ]
}
```
表示例：
![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/396fcddf-5643-0cda-088c-7efb9d773857.png)

３．サジェスト
　以下のJSONでリクエスト

```haml:Header
POST https://smba.trafficmanager.net/apis/v3/conversations/<conversationId>/activities/<replyTokenId>
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
```

```json:JSON
{
    "type": "message",
    "from": {
        "id": "12345678",
        "name": "sender's name"
    },
    "conversation": {
        "id": "abcd1234",
        "name": "conversation's name"
   },
   "recipient": {
        "id": "1234abcd",
        "name": "recipient's name"
    },
    "text": "I have colors in mind, but need your help to choose the best one.",
    "inputHint": "expectingInput",
    "suggestedActions": {
        "actions": [
            {
                "type": "imBack",
                "title": "Blue",
                "value": "Blue"
            },
            {
                "type": "imBack",
                "title": "Red",
                "value": "Red"
            },
            {
                "type": "imBack",
                "title": "Green",
                "value": "Green"
            }
        ]
    },
    "replyToId": "5d5cdc723"
}
```
表示例：
![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/83103/bec3d18d-e793-ff39-3822-741e730a8548.png)


***

まとめ

とりあえずAzurePortalでの解説になっているが、時間を見てアクセストークン発行や各メッセージのRest仕様について追記していきたい。