Copilotなどライセンスを与えたユーザを特定のコミュニティチームのメンバーとして自動で追加する

## こんな人向けの記事です
最近はCopilot for Micorosoft 365や、Teams Premiumなど、Microsoft365 E3ライセンスなどに加えてライセンスを与えることでプラスアルファの機能を付与するようなものが増えてきましたね。有償ライセンスをユーザーに与えるからには、活用してほしいもの。とはいっても、周りに同じサービスを使っているユーザーがいないと、なかなか活用までのハードルは高かったりします。

そこで、ライセンスを与えたユーザーをTeamsのチームに招待してユーザーコミュニティに参加してもらうというのはどうでしょう？　

例えばCopilotコミュニティなら「私はこんな感じで使っているという体験談」や「こんな時に使えるプロンプトはない？」　など。

ユーザー同士横のつながりで盛り上がってくれる仕組みを作れるとよいですよね。

### チームへ自動追加しよう
せっかくなので、ライセンスが与えられているユーザーを、チームへ招待する活動について自動化したいと思います。基本的には以下のような工程を用意します。

1. Power Automate（クラウドフロー）で定期的にGraph APIを用いてライセンスが付与されているユーザーの一覧を取得する
2. 参加させたいチームのMicrosoft365グループのメンバー一覧を取得する
3. ライセンスを持つユーザーと、グループのメンバーを比較し、グループには参加していないユーザー一覧を取得する
4. チームに追加する
4. ウェルカムチャットを追加したユーザーに送信する
4. チームへの追加処理に失敗した場合は、管理者へ通知する

### Graph APIでライセンスを持つユーザーを取得
この方法は以下のQiita記事へ以前に投稿しましたので詳しくはこちらを参考にしてください。

https://qiita.com/DaddyDaddy/items/771dc6f606b8412493aa

調べたいライセンスのSKUIDが必要です。上の記事のようにMicrosoft 365 管理センターの[課金情報]>[ライセンス]から調べてもよいですし、以下の Microsoft Learnのページからダウンロードできる CSVファイルを使って調べることもできます。

https://learn.microsoft.com/ja-jp/entra/identity/users/licensing-service-plan-reference

ちなみに、今回のような取り組みには、このあたりのSKUIDが使うと有用そうです。

+ Microsoft Copilot for Microsoft 365
    + 639dec6b-bb19-468b-871c-c5c441c4b0cb
+ Teams Premium (for Departments)
    + 52ea0e27-ae73-4983-a08f-13561ebdb823
+ SharePoint Syntex
    + f61d4aba-134f-44e9-a2a0-f81a5adb26e4
+ Power BI Pro
    + E3/E5などライセンスに紐づいたものなどいろいろあるので、自テナントでメインに使っているライセンスは管理センターから調べたほうがよさそうです

というわけで、記事に従って Power AutomateからOffice 365 Usersコネクタの「HTTP要求を送信します」アクションに以下のように記述してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/bac84fe9-ede3-254c-307c-0e3c7eeeef8f.png)

```PowerAutomate:フィルター
&$filter=assignedLicenses/any(x:x/skuId eq c42b9cae-ea4f-4ab7-9717-81576235ccac)
```
※上の例では c43.... と記述しているところに、取得したいライセンスのSKUIDを差し替えてください。

```PowerAutomate:エンドポイントURL
https://graph.microsoft.com/v1.0/users?$select=id,mail,displayname,assignedLicenses@{variables('フィルター')}
```

HTTP要求でライセンスに紐づいているユーザーを取得できたら、ユーザーのメールアドレスだけを配列にしましょう。これには「選択」アクションを使います。「開始」にはHTTP要求アクションのvalueを指定します。

それから、ここがポイントなのですが、選択アクションの右下のほうにあるアイコンをクリックして「マップ」モードに切り替えます。その中に item()?['mail']　のように式で指定します。この形は Apply to eachなどでJSONの取得したい箇所を指定するのと同じ書き方ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/e52e6d6c-c5ed-5dd5-41cf-01758b2cae57.png)

テスト実行してみると、ライセンスを持っているユーザーが配列の形で取得できているのがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/9e711d2b-1e57-9e5e-26c7-6fca5c92e96b.png)

### チームを用意してグループIDを確認する
あらかじめTeamsにチームを用意しておきます。今回はCopilotに興味がある人ならば誰でも入ってほしいのでチームの種類をパブリックにしましたが、会社によっては制限されていることもあると思うので、プライベートチームでも構いません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/32145068-94cf-1c53-9e1a-ad99aed41fdd.png)

目当てのチームを管理している Microsoft 365グループを確認するには、[Microsoft 365管理センター](https://admin.microsoft.com/)　　の[チームとグループ]>[アクティブなチームとグループポリシー]　を開き、チーム名と同名のMicrosoft365グループを探します。Microsoft365グループの名称はチームの名称と連動するので、チーム名が変更されると自動的にグループの名前も変わっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/4346c8cf-cade-e8c1-63cc-f5b7b0c0cc33.png)



グループを開いたときのURLの最後のほうにある文字列がグループIDです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/d30ec971-591c-39cb-1ee7-3d26234d6eee.png)

グループのIDは、もちろん [portal.azure.com]　からも確認することができます。ここではオブジェクトIDとして表示されています。(https://portal.azure.com/#view/Microsoft_AAD_IAM/GroupsManagementMenuBlade/~/AllGroups)
)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/ee305b58-94aa-7360-1088-f3b6c862fde1.png)

自分自身が参加しているグループであれば、[マイアカウント](https://myaccount.microsoft.com/)を開いて、[参加しているグループ](https://myaccount.microsoft.com/groups/)を開くことで確認できます。ここでも、グループ名をクリックした際にブラウザに表示されるURLの中にグループIDが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/c524d703-d33a-e6b4-3fb1-9a93a85ae81e.png)

Office 365 Groupsコネクタの「グループメンバーの一覧表示」アクションを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/88a36b04-450b-6093-f8f8-022ceb5eb48d.png)

アクションを選択したらチームのグループIDを指定するのですが・・・。そうか。自分が参加しているチームならここに勝手にチーム名が表示されるので、グループIDをいちいち調べる必要もありませんでしたね。

ちなみにこのアクションで取得できるユーザーの上限は規定で100、手動設定で999です。大きなグループに成長してほしいので999を設定しておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/a1014abe-f7dc-6a5f-4c0e-90f4287e3f41.png)

ちなみに、それ以上のメンバーを取得する場合には、[アクションの設定から「改ページ」設定を行い、ページング処理は手動で作成](https://learn.microsoft.com/ja-jp/connectors/office365groups/#%E3%83%9A%E3%83%BC%E3%82%B8%E5%8C%BA%E5%88%87%E3%82%8A)する必要があります。このあたりはまたいずれ。

グループのメンバーも、「選択」アクションのマップモードを使ってメールアドレスだけの配列にしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/4845b5d3-7434-0ca4-367a-281a309446de.png)

テスト実行してみました。チームにはまだ私しか参加していませんので、私のメールアドレスだけが配列として取得できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/6bb2409e-346c-7d88-0658-e032fe5b3907.png)


### 配列の差集合を取る
これで、「選択」にはライセンスをもつユーザーの配列、「選択 2」にはチームに参加済みのメンバーの配列が入っていることになります。

さて、みんな大好き「集合」のお時間です。ベン図にかいて今回ほしい条件をどのように取得すればよいかチェックします。ライセンスは持っているけれど、グループには参加していないユーザーなので、図のようにグループ参加済みのユーザーで型抜きしたような形になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/249b500f-9dc2-cc03-9cec-840bc24e67e2.png)



クッキーの型抜きをイメージしましょう。この形は[「差集合」](https://ja.wikipedia.org/wiki/%E9%9B%86%E5%90%88)です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/b1ab812c-37af-fc02-28bf-8a978f65bc9a.png)

差集合って、Power Automateでどうすれば取得できるかは、こちらの記事で紹介されてました。なるほど、Contains関数を使うみたいです。

https://qiita.com/k_oshima23/items/cbf66ae53734a9fbc905

クッキー生地がライセンスを持つユーザー（選択）。クッキーの型がグループに参加済みのユーザー（選択 2）です。

「アレイのフィルター処理」アクションを使って、まずは「差出人」に「選択」の出力を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/5565086b-fa73-7c42-9358-b8a98e5541c1.png)

左辺には以下のように式を指定します。Contains関数は第１引数の中に第２引数の値が含まれていればTrueを返します。つまり、この場合はチームに参加済みのユーザーの中に、ライセンスを持つユーザーが含まれているか、１人ずつitem() で与えて比較しているんですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/c06591e6-3775-10c3-9b00-4df37494b975.png)

さらに、右辺には式で「true」を指定します。中央は「次の値に等しくない」を指定しています。これでチームに参加済みのユーザーの中にまだ含まれていないライセンスを持つユーザーをこうやって抽出できるんですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/ea61344a-5423-21fc-4d88-999c0ce2400e.png)

差集合の取得によって、既にチームに参加している私以外のライセンスを持つユーザーが配列として取得できました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/76dba777-b706-5ae5-981f-30346dd3b35d.png)

### チームに追加させる
あとはチームへの参加をApply to eachを使って順番に行えばOKですね。ついでに追加した人達にチャットでメッセージを送ってみます。

Apply to each の最初の欄には「アレイのフィルター処理」の本文「body('アレイのフィルター処理')」を設定します。

「アレイのフィルター処理」の中身はJSONではなくてシンプルな配列ですので、Apply to eachの中に設定したチームへの追加やメッセージの投稿の宛先には　item() だけを設定すれば大丈夫です。これで配列から１つずつのメールアドレスを取得できます。

チームへのメンバー追加の後にはユーザーへの招待メッセージを送る処理と、メンバー追加に失敗した場合の管理者への通知処理を加えました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/e94adb8e-df48-8fae-2647-6259bf6d5a09.png)

このように並列で処理を並べて、片方は上位の処理が失敗した時の条件を構成しておくと、簡単にエラー補足ができるので便利です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/9cc9fa95-f41e-efdd-9e22-236a6a92b115.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/594fafed-9f31-b8ea-80da-9b9f343ed909.png)

### テスト実行する際には注意してくださいね。。。

さて、これで追加するべきユーザーを集めてチームに追加し、さらにはご招待メッセージまで送信できるようになったわけですが。実行には注意してくださいね。Apply to eachの部分まで作りこんだあとで実行すると、実際にたくさんの人がチームへ追加されます。ちゃんと準備しないまま実行してしまうと大騒ぎになったりしますので、実行は計画的に。

次回の投稿では、チームに追加させないユーザーをExcelで管理しようと思います。これに追加対象と判定されたユーザーを全員指定しておけば少しずつリストから外して実稼働に持っていくことができそうです。

実行する際には慎重に！　私の場合はテストテナントなので、テスト実行してみました。

17回ループが回っていずれもチームへの追加とメッセージ送信が成功したようです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/b3fce174-a8ad-5b92-6498-cb349c8aa672.png)

チームを確認すると、ライセンスを持つユーザーさんたちがメンバーとして追加されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/07f0d4c2-a003-21b1-5cd0-6d5143f61a4b.png)

チームに参加したメンバーの一人に届いていたメッセージはこんな感じです。ボットとして投稿したけれど、ユーザーとしてメッセージを送信したほうが親近感があったかな？　チームへのURLを一緒に投稿しておいたほうが良かったかもしれません。実際に動作させるといろいろ発見があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/bee2d5b3-4973-db5c-f629-0cea4c9063dc.png)


## まとめ
ライセンスを与えられているユーザーの取得と、まだチームに参加していないユーザーをMicrosoft365グループとの「差集合」による比較でフィルターし、チームへの追加をすることができました。

今回はライセンスとグループを比較しましたが、２つのチームのメンバーを同期させたり、何かのメール送信の条件に差集合をつかったりといろいろ応用できそうです。何かアイディアがあったらぜひ試してみたいのでコメントで教えてください。