TeamsにBotからプロアクティブメッセージを一斉送信から個別送信にする際の注意点


## はじめに

この記事は実際に Microsoft Teams のBot開発を行っていく過程で初見では気付き辛かった点を取り上げることにしました。
TeamsのBot開発をこれから行っていこうと思っている方や仕様をさらに把握したいと言う方が想定読者としています。

また新しく初めていことに興味がある方は以下から参考にして行くのがおすすめです。

- [【第1/5】Teams bot をローカル (Visual Studio 2019) で開発し、Azure で無料で動かす【その１：VS でローカル web サーバ立てる編】 #decode20 #A02](https://qiita.com/chomado/items/4de8e1f4e5a76fb20bcd)

- [Microsoft Teams のボットについて | 公式ドキュメント](https://docs.microsoft.com/ja-jp/microsoftteams/platform/bots/what-are-bots)

## 注意点

そもそもプロアクティブメッセージの送信周りを送る際には公式のサンプルプログラムでは `conversationReferences` と言う箱に会話で得たユーザー情報を格納しそれを元にメッセージを送信しています。

しかし `conversationReferences` の型について実は **エミュレーター** と実際の **Teams環境** だと違うと言う点に注意しなければなりません。
( 2020年12月現在 )

### 具体的に差分が生じている点

`conversationReferences` とは Bot とユーザーが会話をした際に取得できる型であり、Teamsの本番環境であると `aadObjectId` が取得できます。

`aadObjectId` のマイクロソフトアカウントのユーザーIDのようなもので正式名称は `Azure Active Directory Object Id` となります。

### 本番環境

```json
{
	"FknOjiitVpfBXSFcHiqRep-4": {
		"activityId": "7GCgSxkdWuf",
		"user": {
			"id": "3C0fe770-0131-caf6-9177-88bdf08f351f"
		},
		"bot": {
			"id": "DopponTeamsBotService@59rsZF9eI-o",
			"name": "DopponTeamsBotService"
		},
		"conversation": {
			"id": "FknOjeotHpfBXSFxHiqRep-4"
		},
		"channelId": "webchat",
		"serviceUrl": "https://webchat.botframework.com/"
	},
	"a:1tcdj0cbxSUNmnBnnUCxZPGHfstqtIDTxpGtHRhucYTAnSD37XDt2AhpIniAqswtrIvkTUmNJLARFH4JgC2e-9BD7fq_Gx8uoAQVjQzNrdVmFP_d5mQDPPHjQzNrdVmFP": {
		"activityId": "1602489441525",
		"user": {
			"id": "29:1a6oA8YxSUNmnBnnUCxZPGXszs130PQD_UbDS3jZj5vOBArQJzFGvF5VmfaOBsx5TfaUmo7_eDk-MOBJxpeuZ-A",
			"name": "Doppon Doppon",
			"aadObjectId": "3C0fe770-0131-caf6-9177-88bdf08f351f"
		},
		"bot": {
			"id": "28:4a11a0e6-f4fb-4041-b154-23c4af8754c7",
			"name": "StgKiyosuTeamsBotService"
		},
		"conversation": {
			"conversationType": "personal",
			"tenantId": "3413874b-c75f-4341-a966-51b341e0e73b",
			"id": "a:1tcdj0cbxSUNmnBnnUCxZPGHfstqtIDTxpGtHRhucYTAnSD37XDt2AhpIniAqswtrIvkTUmNJLARFH4JgC2e-9BD7fq_Gx8uoAQVjQzNrdVmFP_d5mQDPPHjQzNrdVmFP"
		},
		"channelId": "msteams",
		"locale": "ja-JP",
		"serviceUrl": "https://smba.trafficmanager.net/jp/"
	}
}
```

### エミュレーター

```json
{
    "99bcaa20-3a5d-11eb-8881-359e54a65776|livechat": {
        "activityId": "99c81bd0-3a5d-11eb-8881-359e54a65776",
        "user": {
            "id": "1cf42a63-2339-4b11-86ff-48a346a05da6",
            "name": "User",
            "role": "user"
        },
        "bot": {
            "id": "99bc0de0-3a5d-11eb-b120-ed176bbc9b31",
            "name": "Bot",
            "role": "bot"
        },
        "conversation": {
            "id": "99bcaa20-3a5d-11eb-8881-359e54a65776|livechat"
        },
        "channelId": "emulator",
        "locale": "en-US",
        "serviceUrl": "http://localhost:58358"
    }
}
```

## 「Webチャットでテスト」の扱い

これも **エミュレーター** と同じ形式で返されます

![スクリーンショット_2020-12-10_8_27_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195292/df2bb067-7748-0714-036c-1f0f6bf612b9.png)

## `aadObjectId` が取得できると嬉しいこと
プロアクティブメッセージ( 通知 )の実装をしたいと思った際にまず公式の[サンプルプログラム](https://github.com/microsoft/BotBuilder-Samples/blob/main/samples/javascript_nodejs/16.proactive-messages/index.js#L72-L78)を参考にすると以下のコードが目に付くと思います。

```js
for (const conversationReference of Object.values(conversationReferences)) {
    await adapter.continueConversation(conversationReference, async turnContext => {
        // If you encounter permission-related errors when sending this message, see
        // https://aka.ms/BotTrustServiceUrl
        await turnContext.sendActivity('proactive hello');
    });
}
```

しかし上記の処理と言うのは取得した `conversationReferences` (全ての送り先)に対して **一括送信** してしまっています。開発の要件に **個別送信** をしようとした際には個別送信を行いたい `conversationReference` に対してユニークなidで検索しなければなりません。
そうなった際に `aadObjectId` が利用できます。

## 参考

- プロアクティブメッセージ: https://docs.microsoft.com/ja-jp/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages?tabs=dotnet#get-the-user-id-or-teamchannel-id

- `conversationReferences`: https://github.com/microsoft/BotBuilder-Samples/blob/main/samples/javascript_nodejs/16.proactive-messages/index.js#L72



## 宣伝

この記事を読んで「面白かった」「学びがあった」と思っていただけた方、よろしければ Twitter や facebook、はてなブックマークにてコメントをお願いします！
また [DeNA 公式 Twitter アカウント @DeNAxTech](https://twitter.com/DeNAxTech) では、 Blog記事だけでなく色々な勉強会での登壇資料も発信してます。ぜひフォローして下さい！
<a href="https://twitter.com/DeNAxTech?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-size="large" data-lang="ja" data-show-count="false">Follow @DeNAxTech</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>